1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * Copyright (c) 2018, Joyent, Inc.
   8  */
   9 
  10 /*
  11  * This program is copyright Alec Muffett 1993. The author disclaims all
  12  * responsibility or liability with respect to it's usage or its effect
  13  * upon hardware or computer systems, and maintains copyright as set out
  14  * in the "LICENCE" document which accompanies distributions of Crack v4.0
  15  * and upwards.
  16  */
  17 
  18 #include "packer.h"
  19 
  20 void
  21 PWRemove(char *path)
  22 {
  23         char fname[PATH_MAX];
  24 
  25         (void) snprintf(fname, sizeof (fname), "%s/%s", path,
  26             DICT_DATABASE_PWI);
  27         (void) unlink(fname);
  28         (void) snprintf(fname, sizeof (fname), "%s/%s", path,
  29             DICT_DATABASE_PWD);
  30         (void) unlink(fname);
  31         (void) snprintf(fname, sizeof (fname), "%s/%s", path,
  32             DICT_DATABASE_HWM);
  33         (void) unlink(fname);
  34 }
  35 
  36 PWDICT *
  37 PWOpen(char *path, char *mode)
  38 {
  39         PWDICT *pdesc;
  40         char iname[PATH_MAX];
  41         char dname[PATH_MAX];
  42         char wname[PATH_MAX];
  43         int fd_d;
  44         int fd_i;
  45         int fd_w;
  46         FILE *dfp;
  47         FILE *ifp;
  48         FILE *wfp;
  49 
  50         if ((pdesc = calloc(1, sizeof (PWDICT))) == NULL)
  51                 return ((PWDICT *) 0);
  52 
  53         if (pdesc->header.pih_magic == PIH_MAGIC) {
  54                 return ((PWDICT *) 0);
  55         }
  56         (void) memset(pdesc, '\0', sizeof (pdesc));
  57 
  58         (void) snprintf(iname, sizeof (iname), "%s/%s", path,
  59             DICT_DATABASE_PWI);
  60         (void) snprintf(dname, sizeof (dname), "%s/%s", path,
  61             DICT_DATABASE_PWD);
  62         (void) snprintf(wname, sizeof (wname), "%s/%s", path,
  63             DICT_DATABASE_HWM);
  64 
  65         if ((fd_d = open(dname, O_RDWR|O_CREAT, 0600)) == -1)
  66                 syslog(LOG_ERR, "PWopen: can't open %s: %s", dname,
  67                     strerror(errno));
  68         if ((fd_i = open(iname, O_RDWR|O_CREAT, 0600)) == -1)
  69                 syslog(LOG_ERR, "PWopen: can't open %s: %s", iname,
  70                     strerror(errno));
  71         if ((fd_w = open(wname, O_RDWR|O_CREAT, 0600)) == -1)
  72                 syslog(LOG_ERR, "PWopen: can't open %s: %s", wname,
  73                     strerror(errno));
  74 
  75         if (!(pdesc->dfp = fdopen(fd_d, mode))) {
  76                 return ((PWDICT *) 0);
  77         }
  78 
  79         if (!(pdesc->ifp = fdopen(fd_i, mode))) {
  80                 (void) fclose(pdesc->dfp);
  81                 return ((PWDICT *) 0);
  82         }
  83 
  84         if (pdesc->wfp = fdopen(fd_w, mode)) {
  85                 pdesc->flags |= PFOR_USEHWMS;
  86         }
  87 
  88         ifp = pdesc->ifp;
  89         dfp = pdesc->dfp;
  90         wfp = pdesc->wfp;
  91 
  92         if (mode[0] == 'w') {
  93                 pdesc->flags |= PFOR_WRITE;
  94                 pdesc->header.pih_magic = PIH_MAGIC;
  95                 pdesc->header.pih_blocklen = NUMWORDS;
  96                 pdesc->header.pih_numwords = 0;
  97 
  98                 (void) fwrite((char *)&(pdesc->header), sizeof (pdesc->header),
  99                     1, ifp);
 100         } else {
 101                 pdesc->flags &= ~PFOR_WRITE;
 102 
 103                 if (!fread((char *)&(pdesc->header), sizeof (pdesc->header),
 104                     1, ifp)) {
 105                         pdesc->header.pih_magic = 0;
 106                         (void) fclose(ifp);
 107                         (void) fclose(dfp);
 108                         return ((PWDICT *) 0);
 109                 }
 110 
 111                 if (pdesc->header.pih_magic != PIH_MAGIC) {
 112                         pdesc->header.pih_magic = 0;
 113                         (void) fclose(ifp);
 114                         (void) fclose(dfp);
 115                         return ((PWDICT *) 0);
 116                 }
 117 
 118                 if (pdesc->header.pih_blocklen != NUMWORDS) {
 119                         pdesc->header.pih_magic = 0;
 120                         (void) fclose(ifp);
 121                         (void) fclose(dfp);
 122                         return ((PWDICT *) 0);
 123                 }
 124 
 125                 if (pdesc->flags & PFOR_USEHWMS) {
 126                         if (fread(pdesc->hwms, 1, sizeof (pdesc->hwms), wfp) !=
 127                             sizeof (pdesc->hwms)) {
 128                                 pdesc->flags &= ~PFOR_USEHWMS;
 129                         }
 130                 }
 131         }
 132         return (pdesc);
 133 }
 134 
 135 int
 136 PWClose(PWDICT *pwp)
 137 {
 138         if (pwp->header.pih_magic != PIH_MAGIC) {
 139                 return (-1);
 140         }
 141 
 142         if (pwp->flags & PFOR_WRITE) {
 143                 pwp->flags |= PFOR_FLUSH;
 144                 (void) PutPW(pwp, (char *)0);   /* flush last index if necess */
 145 
 146                 if (fseek(pwp->ifp, 0L, 0)) {
 147                         return (-1);
 148                 }
 149 
 150                 if (!fwrite((char *)&pwp->header, sizeof (pwp->header),
 151                     1, pwp->ifp)) {
 152                         return (-1);
 153                 }
 154 
 155                 if (pwp->flags & PFOR_USEHWMS) {
 156                         int i;
 157                         for (i = 1; i <= 0xff; i++) {
 158                                 if (!pwp->hwms[i]) {
 159                                         pwp->hwms[i] = pwp->hwms[i-1];
 160                                 }
 161                         }
 162                         (void) fwrite(pwp->hwms, 1, sizeof (pwp->hwms),
 163                             pwp->wfp);
 164                 }
 165         }
 166 
 167         (void) fclose(pwp->ifp);
 168         (void) fclose(pwp->dfp);
 169         (void) fclose(pwp->wfp);
 170 
 171         pwp->header.pih_magic = 0;
 172 
 173         free(pwp);
 174 
 175         return (0);
 176 }
 177 
 178 int
 179 PutPW(PWDICT *pwp, char *string)
 180 {
 181         if (!(pwp->flags & PFOR_WRITE)) {
 182                 return (-1);
 183         }
 184 
 185         if (string) {
 186                 (void) strncpy(pwp->data[pwp->count], string, MAXWORDLEN);
 187                 pwp->data[pwp->count][MAXWORDLEN - 1] = '\0';
 188 
 189                 pwp->hwms[string[0] & 0xff] = pwp->header.pih_numwords;
 190 
 191                 ++(pwp->count);
 192                 ++(pwp->header.pih_numwords);
 193 
 194         } else if (!(pwp->flags & PFOR_FLUSH)) {
 195                 return (-1);
 196         }
 197 
 198         if ((pwp->flags & PFOR_FLUSH) || !(pwp->count % NUMWORDS)) {
 199                 int i;
 200                 uint32_t datum;
 201                 register char *ostr;
 202 
 203                 datum = (uint32_t)ftell(pwp->dfp);
 204 
 205                 (void) fwrite((char *)&datum, sizeof (datum), 1, pwp->ifp);
 206 
 207                 (void) fputs(pwp->data[0], pwp->dfp);
 208                 (void) putc(0, pwp->dfp);
 209 
 210                 ostr = pwp->data[0];
 211 
 212                 for (i = 1; i < NUMWORDS; i++) {
 213                         register int j;
 214                         register char *nstr;
 215 
 216                         nstr = pwp->data[i];
 217 
 218                         if (nstr[0]) {
 219                                 for (j = 0; ostr[j] && nstr[j] &&
 220                                     (ostr[j] == nstr[j]); j++)
 221                                         ;
 222                                 (void) putc(j & 0xff, pwp->dfp);
 223                                 (void) fputs(nstr + j, pwp->dfp);
 224                         }
 225                         (void) putc(0, pwp->dfp);
 226 
 227                         ostr = nstr;
 228                 }
 229 
 230                 (void) memset(pwp->data, '\0', sizeof (pwp->data));
 231                 pwp->count = 0;
 232         }
 233         return (0);
 234 }
 235 
 236 char *
 237 GetPW(PWDICT *pwp, uint32_t number)
 238 {
 239         uint32_t datum;
 240         register int i;
 241         register char *ostr;
 242         register char *nstr;
 243         register char *bptr;
 244         char buffer[NUMWORDS * MAXWORDLEN];
 245         static char data[NUMWORDS][MAXWORDLEN];
 246         static uint32_t prevblock = 0xffffffff;
 247         uint32_t thisblock;
 248 
 249         thisblock = number / NUMWORDS;
 250 
 251         if (prevblock == thisblock) {
 252                 return (data[number % NUMWORDS]);
 253         }
 254 
 255         if (fseek(pwp->ifp, sizeof (struct pi_header) +
 256             (thisblock * sizeof (uint32_t)), 0)) {
 257                 return (NULL);
 258         }
 259 
 260         if (!fread((char *)&datum, sizeof (datum), 1, pwp->ifp)) {
 261                 return (NULL);
 262         }
 263 
 264         if (fseek(pwp->dfp, datum, 0)) {
 265                 return (NULL);
 266         }
 267 
 268         if (!fread(buffer, 1, sizeof (buffer), pwp->dfp)) {
 269                 return (NULL);
 270         }
 271 
 272         prevblock = thisblock;
 273 
 274         bptr = buffer;
 275 
 276         for (ostr = data[0]; *(ostr++) = *(bptr++); /* nothing */)
 277                 ;
 278 
 279         ostr = data[0];
 280 
 281         for (i = 1; i < NUMWORDS; i++) {
 282                 nstr = data[i];
 283                 (void) strcpy(nstr, ostr);
 284                 ostr = nstr + *(bptr++);
 285                 while (*(ostr++) = *(bptr++))
 286                         ;
 287 
 288                 ostr = nstr;
 289         }
 290 
 291         return (data[number % NUMWORDS]);
 292 }
 293 
 294 uint32_t
 295 FindPW(PWDICT *pwp, char *string)
 296 {
 297         int lwm;
 298         int hwm;
 299         int idx;
 300 
 301         if (string == NULL)
 302                 return (PW_WORDS(pwp));
 303 
 304         if (pwp->flags & PFOR_USEHWMS) {
 305                 idx = string[0] & 0xff;
 306                 lwm = idx ? pwp->hwms[idx - 1] : 0;
 307                 hwm = pwp->hwms[idx];
 308         } else {
 309                 lwm = 0;
 310                 hwm = PW_WORDS(pwp) - 1;
 311         }
 312 
 313         for (;;) {
 314                 int cmp;
 315                 int pivot;
 316                 char *this;
 317 
 318                 pivot = lwm + ((hwm+1)-lwm)/2;
 319 
 320                 if (feof(pwp->ifp) && feof(pwp->dfp) && feof(pwp->wfp))
 321                         break;
 322 
 323                 if ((this = GetPW(pwp, pivot)) == NULL)
 324                         break;
 325 
 326                 cmp = strcmp(string, this);             /* INLINE ? */
 327 
 328                 if (cmp == 0)
 329                         return (pivot);
 330                 else if (cmp < 0)
 331                         hwm = pivot-1;
 332                 else
 333                         lwm = pivot+1;
 334 
 335                 if (lwm > hwm)       /* searched all; not found */
 336                         break;
 337         }
 338 
 339         /* not found */
 340         return (PW_WORDS(pwp));
 341 }