Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:15

0001 /*-
0002  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
0003  *
0004  * Copyright (c) 2003 Poul-Henning Kamp
0005  * All rights reserved.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0020  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0021  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0022  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0023  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0024  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0025  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0026  * SUCH DAMAGE.
0027  */
0028 
0029 #include <sys/cdefs.h>
0030 __FBSDID("$FreeBSD$");
0031 
0032 #include <sys/types.h>
0033 
0034 #include <md5.h>
0035 #include <stdio.h>
0036 #include <string.h>
0037 #include <unistd.h>
0038 
0039 #include <crypt.h>
0040 
0041 #define MD5_SIZE 16
0042 
0043 /*
0044  * UNIX password
0045  */
0046 
0047 char *
0048 crypt_md5_r(const char *pw, const char *salt, struct crypt_data *data)
0049 {
0050     MD5_CTX ctx,ctx1;
0051     unsigned long l;
0052     int sl, pl;
0053     u_int i;
0054     u_char final[MD5_SIZE];
0055     const char *sp, *ep;
0056     char *passwd = &data->buffer[0], *p;
0057     static const char magic[] = "$1$";
0058 
0059     /* Refine the Salt first */
0060     sp = salt;
0061 
0062     /* If it starts with the magic string, then skip that */
0063     if(!strncmp(sp, magic, strlen(magic)))
0064         sp += strlen(magic);
0065 
0066     /* It stops at the first '$', max 8 chars */
0067     for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
0068         continue;
0069 
0070     /* get the length of the true salt */
0071     sl = ep - sp;
0072 
0073     MD5Init(&ctx);
0074 
0075     /* The password first, since that is what is most unknown */
0076     MD5Update(&ctx, (const u_char *)pw, strlen(pw));
0077 
0078     /* Then our magic string */
0079     MD5Update(&ctx, (const u_char *)magic, strlen(magic));
0080 
0081     /* Then the raw salt */
0082     MD5Update(&ctx, (const u_char *)sp, (u_int)sl);
0083 
0084     /* Then just as many characters of the MD5(pw,salt,pw) */
0085     MD5Init(&ctx1);
0086     MD5Update(&ctx1, (const u_char *)pw, strlen(pw));
0087     MD5Update(&ctx1, (const u_char *)sp, (u_int)sl);
0088     MD5Update(&ctx1, (const u_char *)pw, strlen(pw));
0089     MD5Final(final, &ctx1);
0090     for(pl = (int)strlen(pw); pl > 0; pl -= MD5_SIZE)
0091         MD5Update(&ctx, (const u_char *)final,
0092             (u_int)(pl > MD5_SIZE ? MD5_SIZE : pl));
0093 
0094     /* Don't leave anything around in vm they could use. */
0095     memset(final, 0, sizeof(final));
0096 
0097     /* Then something really weird... */
0098     for (i = strlen(pw); i; i >>= 1)
0099         if(i & 1)
0100             MD5Update(&ctx, (const u_char *)final, 1);
0101         else
0102             MD5Update(&ctx, (const u_char *)pw, 1);
0103 
0104     /* Now make the output string */
0105     strcpy(passwd, magic);
0106     strncat(passwd, sp, (u_int)sl);
0107     strcat(passwd, "$");
0108 
0109     MD5Final(final, &ctx);
0110 
0111     /*
0112      * and now, just to make sure things don't run too fast
0113      * On a 60 Mhz Pentium this takes 34 msec, so you would
0114      * need 30 seconds to build a 1000 entry dictionary...
0115      */
0116     for(i = 0; i < 1000; i++) {
0117         MD5Init(&ctx1);
0118         if(i & 1)
0119             MD5Update(&ctx1, (const u_char *)pw, strlen(pw));
0120         else
0121             MD5Update(&ctx1, (const u_char *)final, MD5_SIZE);
0122 
0123         if(i % 3)
0124             MD5Update(&ctx1, (const u_char *)sp, (u_int)sl);
0125 
0126         if(i % 7)
0127             MD5Update(&ctx1, (const u_char *)pw, strlen(pw));
0128 
0129         if(i & 1)
0130             MD5Update(&ctx1, (const u_char *)final, MD5_SIZE);
0131         else
0132             MD5Update(&ctx1, (const u_char *)pw, strlen(pw));
0133         MD5Final(final, &ctx1);
0134     }
0135 
0136     p = passwd + strlen(passwd);
0137 
0138     l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
0139     _crypt_to64(p, l, 4); p += 4;
0140     l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
0141     _crypt_to64(p, l, 4); p += 4;
0142     l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
0143     _crypt_to64(p, l, 4); p += 4;
0144     l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
0145     _crypt_to64(p, l, 4); p += 4;
0146     l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
0147     _crypt_to64(p, l, 4); p += 4;
0148     l = final[11];
0149     _crypt_to64(p, l, 2); p += 2;
0150     *p = '\0';
0151 
0152     /* Don't leave anything around in vm they could use. */
0153     memset(final, 0, sizeof(final));
0154 
0155     return (passwd);
0156 }
0157 
0158 struct crypt_format crypt_md5_format =
0159     CRYPT_FORMAT_INITIALIZER(crypt_md5_r, "$1$");