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