Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

passwd.c

Go to the documentation of this file.
00001 
00015 #include "services.h"
00016 #include <time.h>
00017 #include <ctype.h>
00018 #include <string.h>
00019 
00020 #include "hash/md5.h"
00021 #include "hash/md5pw.h"
00022 
00023 #ifndef __cplusplus
00024 
00025 typedef unsigned char bool;
00026 #endif
00027 
00028 /*************************************************************************/
00029 
00042 unsigned char *toBase64(const unsigned char *stream, size_t left)
00043 {
00044     #define X_OUTPUT_MAP_SZ 64
00045     const unsigned char mutations[] =
00046         "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
00047         "0123456789+/";
00048     unsigned int j, k, s_sz = 0, acc;
00049     unsigned char temp[3], out[4];
00050     char *s = NULL, *p;
00051 
00052     j = acc = 0;
00053 
00054     // Calculate the length increase from the conversion from
00055     // 8 bit to 6 bit encoding. We will even provide a null terminator.
00056 
00057     s_sz = (((left * 8) / 24) * 4) +
00058         ((((left * 8) % 24)) ? 3 : 0) +
00059         2;
00060 
00061 
00062     p = s = (char *)oalloc(s_sz + 1);
00063 
00064     for ( ; left ; )
00065     {
00066         while ( left > 0 && j < 3 ) {
00067             temp[j++] = *stream;
00068             left--;
00069             stream++;
00070         }
00071 
00072         //
00073         // Alphabetic approximation of what our
00074         // bitwise operations need to accomplish
00075         //
00076         // ABCDEFGH IJKLMNOP QRSTUVWX --------
00077         // ABCDEFGH IJKLMNOP QRSTUVWX STUVWX--
00078         // --ABCDEF ABCDEFGH --MNOP-- STUVWX--
00079         // 00111111 00000011 ------QR STUVWX--
00080         // --ABCDEF ------GH --MNOPQR STUVWX--
00081         // --ABCDEF ----GH-- --MNOPQR STUVWX--
00082         // --ABCDEF ----IJKL --MNOPQR STUVWX--
00083         // --ABCDEF --GHIJKL --MNOPQR STUVWX--
00084         // --ABCDEF --GHIJKL --MNOPQR STUVWX--
00085         //
00086 
00087         // Stuff the first 6 bits into the 1st 6-bit counter
00088         // Shift it over so that the 2 high bits are
00089         // zero
00090         out[0] = (temp[0] >> 2);
00091 
00092         // Stuff the last two bits of the first byte into
00093         // the second counter -- shift it into the high
00094         // bits.  Carry in the next 4 bits
00095         {
00096             if (j < 3) {
00097                 temp[2] = 0;
00098                 if (j < 2)
00099                     temp[1] = 0;
00100             }
00101 
00102             out[1] = ((temp[0] & 0x03) << 4) |
00103                      (temp[1] >> 4);
00104 
00105             // Lather, rinse, repeat
00106 
00107             // 00001111 -> 0x0f
00108             out[2] = ( (temp[1] & 0x0f) << 2 ) |
00109                      ( temp[2] >> 6 );
00110 
00111             // 00111111 ->  0x3f
00112             out[3] = (temp[2] & 0x3f);
00113         }
00114 
00115         for(k = 0; k < 4; k++) {
00116             if ( k <= j ) {
00117                 assert(out[k] < X_OUTPUT_MAP_SZ);
00118                 *p++ = mutations[out[k]];
00119             }
00120             else    *p++ = '=';
00121             if (--s_sz < 1)
00122                 assert(s_sz >= 1);
00123         }
00124 
00125         j = 0;
00126     }
00127 
00128     *p++ = '\0';
00129 
00130     #undef X_OUTPUT_MAP_SZ 64
00131     return (unsigned char *)s;
00132 }
00133 
00144 unsigned char *fromBase64(const char *cStr, int *len)
00145 {
00146     #define X_OUTPUT_MAP_SZ 64
00147     const unsigned char mutations[] =
00148         "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
00149         "0123456789+/";
00150     static unsigned char decode_table[255] = {};
00151     static int pFlag = 0;
00152     int i, j, k, s_sz = 0, hitz = 0;
00153     unsigned char temp[4], out[4], c;
00154     unsigned char *s = NULL, *p;
00155     size_t left = strlen(cStr);
00156 
00157 
00158     if (pFlag == 0)
00159     {
00160         pFlag = 1;
00161 
00162         for(j = 0; j < 127; j++)
00163             decode_table[j] = '\0';
00164 
00165         for(j = 0; j < 64; j++) {
00166             for(i = 0; i < 127; i++) {
00167                 if (i == mutations[j]) {
00168                     decode_table[i] = j;
00169                     break;
00170                 }
00171             }
00172         }
00173         pFlag = 1;
00174     }
00175 
00176     // For every 4 characters we have, we have 24 bits of output.
00177         // 24 / 8 ==> 3 bytes
00178 
00179     s_sz = 3 + (int) ((left / 4.0) * 3);
00180 
00181     p = s = (unsigned char *)oalloc(s_sz + 1 + 10);
00182 
00183     for ( ; left > 0 ; )
00184     {
00185         j = 0;
00186         hitz = 0;
00187 
00188         while(j < 4 && left > 0) {
00189             c = *(cStr++);
00190             if ((unsigned char)temp[j] < sizeof(decode_table))
00191                 c = decode_table[(unsigned char)c];
00192             else { c = '\0'; hitz = 1; }
00193 
00194             if (hitz == 0) {
00195                 temp[j] = c;
00196                 j++;
00197             }
00198             left--;
00199         }
00200         for(k = j; k < 4; k++)
00201             temp[k] = 0;
00202 
00203         // --ABCDEF --GHIJKL --MNOPQR STUVWX--
00204         // ABCDEFGH IJKL---- QR------
00205         // ------GH ----MNOP --STUVWX
00206 
00207         out[0] = (temp[0] << 2) | ((temp[1] >> 4) & 0x03);
00208         out[1] = (temp[1] << 4) | ((temp[2] >> 2));
00209         out[2] = (temp[2] << 6) | temp[3];
00210 
00211         if (s_sz > 0) {
00212             *(p++) = out[0];
00213             s_sz--;
00214         }
00215 
00216         if (s_sz > 0) {
00217             *(p++) = out[1];
00218             s_sz--;
00219         }
00220 
00221         if (j >= 4) {
00222             (*(p++)) = out[2];
00223             s_sz--;
00224         }
00225 
00226         if (s_sz <= 0) {
00227             assert(s_sz > 0);
00228         }
00229     }
00230 
00231     if (len)
00232         (*len) = (size_t)(p - s);
00233 
00234     *p++ = '\0';
00235 
00236     return (unsigned char *)s;
00237     #undef X_OUTPUT_MAP_SZ
00238 }
00239 
00240 /*
00241  * -> Base on 100million in the most gruesome way imaginable and map it
00242  * into 65 characters, in a peculiar way, the heck? *snick* 
00243  *
00244  * -Mysid 
00245  */
00246 
00247 static char *ExpressAsHighIntBase(u_int32_t value)
00248 {
00249    static char result[256];
00250    char *x_output_map[] = {
00251         "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
00252         "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
00253         "-", "_", /*"0",*/ "1", "2", "3", "4", "5", "6", "7", "8", "9", "/",
00254         "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
00255         "N", "$", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
00256 
00257         "*", "+", "=", "\\", "&", "^", "#", "@", "!", "{",
00258         "(", "[" "?", "'", "\"", "]", ")", ")", ",", ".",
00259         "<", ">", "%", "`", /*after this point not used*/"|", "`", ""
00260    };
00261    #define X_OUTPUT_MAP_SZ 88
00262    #define X_BASE_ENCODING ULONG_MAX
00263    int i = 0, x = 99;
00264    u_int32_t rem;
00265 
00266    for(i = 0; i < 100; i++)
00267        result[i] = '\0';
00268 
00269    while(value > 0) {
00270         rem = (value % X_BASE_ENCODING);
00271         value = (int) value / X_BASE_ENCODING;
00272         if ((rem >= X_BASE_ENCODING))
00273             break;
00274         result[x--] = *x_output_map[((unsigned char)rem) % X_OUTPUT_MAP_SZ];
00275         if (x < 0 || value < 1)
00276             break;
00277    }
00278 
00279    if (x < 99)
00280        for(i = 0; !result[i]; i++) ;
00281    else i = 0;
00282 
00283    return (result + i);
00284    #undef X_OUTPUT_MAP_SZ
00285    #undef X_BASE_ENCODING
00286 }
00287 
00298 const char *GetAuthChKey(const char *email, const char *password,
00299                          time_t timereg, u_int32_t code_arg)
00300 {
00301     u_char digest[16];
00302     static char tresult[256];
00303     struct MD5Context ctx;
00304     uint32 buf[PASSLEN+8];
00305     uint32 md5buf[16];
00306 
00307     int cnt = 0, o = 0;
00308 
00309     int i, j, k, l;
00310 
00311     i = l = 0;
00312     memset(buf, 0, sizeof(buf));
00313 
00314     buf[l++] = (timereg & 65280UL) | (timereg & 4278190080UL); /* 1 */
00315     buf[l++] = (timereg & 255UL) | (timereg & 16711680UL);
00316     buf[l++] = (code_arg & 255UL) | (code_arg & 65280UL);
00317     buf[l++] = 0x7f0a528;
00318     buf[l++] = 0x3011f3f; /* 5 */
00319 
00320     for(i = 0; password[i] && i <= PASSLEN; i++) /* PASSLEN */
00321         buf[l++] = password[i];
00322     buf[l++] = 0x0; /* 6 */
00323 
00324     for(i = 0; i < l; i++) {
00325         buf[i] ^= (code_arg & 4278190080UL);
00326         buf[i] ^= (code_arg & 16711680UL);
00327     }
00328 
00329     buf[l++] = 0x162a34b; /* 7 */
00330 
00331     MD5Init(&ctx);
00332 
00333     for(j = 0 ;; j += 16 ) {
00334         if (j >= l)
00335             break;
00336         k = 0;
00337 
00338         for(i = j; i < j+16; i++) {
00339             if (i >= l) {
00340                 do {
00341                     md5buf[j+i] = k ^ ((code_arg & 255) << 1);
00342                 } while(++i < 16);
00343                 break;
00344             }
00345             md5buf[j+i] = buf[i];
00346             buf[i] = 0;
00347         }
00348         MD5Transform(ctx.buf, md5buf);
00349     }
00350 
00351     MD5Update(&ctx, (unsigned const char *)email, strlen(email));
00352     MD5Final(digest, &ctx);
00353     MD5Init(&ctx);
00354     memset(buf, 0, sizeof(buf));
00355 
00356     *tresult = '\0';
00357         memset(tresult, 0, 255);
00358     for(cnt = 0; cnt < 16; ++cnt)
00359         o += sprintf(tresult+o, "%s", ExpressAsHighIntBase(digest[cnt]));
00360     return tresult;
00361 }
00362 
00363 /*************************************************************************/
00364 
00365 /* Verify the relative security of a password - Not actually used */
00366 
00367 static int pwd_too_simple(const char *newp)
00368 {
00369     int count_digit = 0,    count_upper = 0;
00370     int count_lower = 0,    count_misc = 0;
00371         int req_len;
00372         int i;
00373 
00374         for (i = 0;newp[i];i++) {
00375                 if (isupper (newp[i]))
00376                         count_upper++;
00377                 else if (isdigit (newp[i]))
00378                         count_digit++;
00379                 else if (islower (newp[i]))
00380                         count_lower++;
00381                 else
00382                         count_misc++;
00383         }
00384 
00385         req_len = 7;
00386         if (count_digit > 0) --req_len;
00387         if (count_upper > 0) --req_len;
00388         if (count_lower) --req_len;
00389         if (count_misc) --req_len;
00390 
00391         if (req_len <= i)
00392                 return 0;
00393 
00394         return 1;
00395 }
00396 
00397 /*************************************************************************/
00398 
00399 int mpwd_too_simple(char *epwd, RegNickList *nick)
00400 {
00401      char pwd[MAXBUF];
00402 
00403      if (!epwd || !nick)
00404          return 1;
00405      strncpy(pwd, epwd, MIN(MAXBUF, 80));
00406      pwd[MAXBUF - 1] = '\0';
00407 
00408 #ifdef CRACKLIB_DICTPATH
00409      if (nick)
00410      {
00411           char *msg;
00412           if ((msg = (char *) FascistCheck(pwd, CRACKLIB_DICTPATH))) {
00413               sSend(":%s NOTICE %s :That password you specified not safe because %s.", NickServ, nick->nick);
00414               return 1;
00415           }
00416      }
00417      /* if (nick && (pwd_too_simple(pwd))) {
00418          sSend(":%s NOTICE %s :That password is too short.", NickServ, nick->nick);
00419          return 1;
00420      } */
00421 #else
00422      if (nick && (pwd_too_simple(pwd))) {
00423          sSend(":%s NOTICE %s :That password is too short, try again.", NickServ, nick->nick);
00424          return 1;
00425      }
00426 
00427 #endif /* CRACKLIB_DICTPATH */
00428      return 0;
00429 }
00430 
00440 const char *PrintPass(u_char pI[], char enc)
00441 {
00442     static char buf[256];
00443 
00444     if (enc == '$' || enc == '+') {
00445         u_char *p = toBase64(pI, 16);
00446         if (!p)
00447             abort();
00448         strncpy(buf, (char *)p, sizeof(buf));
00449         buf[sizeof(buf) - 1] = '\0';
00450         FREE(p);
00451         return buf;
00452     }
00453     else
00454         return (char *)pI;
00455 }
00456 
00464 int isPasswordAcceptable(const char* password, char* reason)
00465 {
00466     if (!password || !*password) {
00467         strcpy(reason, "Blank passwords are not allowed.");
00468         return 0;
00469     }
00470     
00471     if  (isMD5Key(password)) {
00472         strcpy(reason, "Try using a password that doesn't start with MD5(.");
00473         return 0;
00474     }
00475     
00476     if (password[0] == '$' && password[1] == '_') {
00477         strcpy(reason, "Try using a password that doesn't start with $_.");
00478         return 0;       
00479     }
00480     return 1;
00481 }
00482 
00483 
00484 /*
00485  * Copyright (c) 2000, 2001 James Hess
00486  * All rights reserved.
00487  *
00488  * Redistribution and use in source and binary forms, with or without
00489  * modification, are permitted provided that the following conditions
00490  * are met:
00491  * 1. Redistributions of source code must retain the above copyright
00492  *    notice, this list of conditions and the following disclaimer.
00493  * 2. Redistributions in binary form must reproduce the above copyright
00494  *    notice, this list of conditions and the following disclaimer in the
00495  *    documentation and/or other materials provided with the distribution.
00496  * 3. Neither the name of the authors nor the names of its contributors
00497  *    may be used to endorse or promote products derived from this software
00498  *    without specific prior written permission.
00499  *
00500  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00501  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00502  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00503  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00504  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00505  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00506  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00507  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00508  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00509  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00510  * SUCH DAMAGE.
00511  */
00512 

Generated at Sat Oct 25 20:56:09 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.