/* * crp.c * spd@daphne.cps.unizar.es * * crypt/compare strings using serveral standard methods * * - crypt (unix standard) * - crypt16 (Tru64) (other: define MY_CRYPT16, link modified libufc) * - bigcrypt (HP-UX, Tru64) (other: define MY_BIGCRYPT) * - md5 (linux) (other: define USE_MD5, link md5crypt) * - LanManager/NT (define USE_SMB, link samba 2.0.9) * * * For SunOS 4.1.x, use gcc * For __convexc__, link with libufc * For linux, if "undefined reference to `crypt'" link with -lcrypt gcc -DMY_BIGCRYPT -DUSE_BIGCRYPT -o crp crp.c -lcrypt for linux, if you want to use crypt16, you have to rename crypt function in ufc-crypt/crypt_util.c to Ucrypt (for instance) See Makefile * For HP-UX, if "Unsatisfied symbols: bigcrypt" link with -lsec cc -Ae -o crp crp.c -lsec cc -Aa -D_HPUX_SOURCE -o crp crp.c -lsec * For Tru64, if "ld: Unresolved: bigcrypt" link with -lsecurity cc -DUSE_BIGCRYPT -o crp crp.c -lsecurity * * For Solaris 2.x or IRIX 6.x cc -I/usr/local/include -DUSE_CRYPT16 -DMY_CRYPT16 \ -DMY_BIGCRYPT -DUSE_BIGCRYPT crp.c -o crp -L/usr/local/lib -lufc * */ static char __ident[] = "@(#)(c) SPDsoft, 0.0 May 24 2001"; #define VERS_STR ((char*)&__ident[4]) #if ( defined __sun__ && !defined __svr4__ ) # define _BSD_ #endif #if defined __linux__ # define _XOPEN_SOURCE # ifndef NO_MD5 # define USE_MD5 # endif #endif #if defined _HPUX_SOURCE # ifndef NO_BIGCRYPT # define USE_BIGCRYPT # endif /* HP-UX 11 bigcrypt(3C) bigcrypt() acts like crypt(3C), but handles much larger strings. bigcrypt takes the segments of cleartext and encrypts them individually, at first using the salt passed in, and then using the first two characters of the previous encrypted segment as the salt for the next segment. This avoids duplicated ciphertext chunks when the password characters are repeated, so that the encryption of a segment involves the encryption of all the previous segments. Each chipertext segment is concatenated, with the salt at the beginning, to form the entire encrypted string. */ #endif #if defined __osf__ /* Tru64 5.0 crypt(3) The crypt16 subroutine is identical to the crypt function except that it will accept a password up to sixteen characters in length. It generates a longer encrypted password for use with enhanced security features. */ # ifndef NO_CRYPT16 # define USE_CRYPT16 # endif /* * crypt16 will give as second half hash crypt("",salt)+2 if l<=8 */ #endif #ifdef USE_MD5 # ifndef __linux__ /* * requires crypt_md5.o and md5.o from md5crypt-1.0 * http://www.ibiblio.org/pub/Linux/apps/crypto/md5crypt-1.0.tar.gz */ extern char *__md5_crypt(const char *, const char *); # endif #endif #include #include #include #include #include #include #include #if !(defined _HPUX_SOURCE) && !(defined __convexc__) && \ !(defined _BSD_) && !(defined __linux__) && !(defined __APPLE__ ) # include #endif #if (defined __convexc__) || (defined _BSD_) char *crypt(const char *key, const char *salt); #endif #ifdef USE_BIGCRYPT # ifndef MY_BIGCRYPT # if defined _HPUX_SOURCE # include # endif # if defined __osf__ # include # endif # include # else char *my_bigcrypt(const char *key, const char *salt); # define bigcrypt my_bigcrypt # endif # ifndef AUTH_MAX_PASSWD_LENGTH # define AUTH_MAX_PASSWD_LENGTH 80 # endif #endif #ifdef USE_CRYPT16 # ifdef MY_CRYPT16 # include char *my_crypt16(const char *key, const char *salt); # define crypt16 my_crypt16 # endif #endif #ifdef USE_SMB /* * * From ENCRYPTION.txt for Samba release 2.0.6 * - LanManager encryption LanManager encryption is somewhat similar to UNIX password encryption. The server uses a file containing a hashed value of a user's password. This is created by taking the user's plaintext password, capitalising it, and either truncating to 14 bytes (or padding to 14 bytes with null bytes). This 14 byte value is used as two 56 bit DES keys to encrypt a 'magic' eight byte value, forming a 16 byte value which is stored by the server and client. Let this value be known as the *hashed password*. - Windows NT encryption Windows NT encryption is a higher quality mechanism, consisting of doing an MD4 hash on a Unicode version of the user's password. This also produces a 16 byte hash value that is non-reversible. */ /*#include "includes.h"*/ #define slprintf snprintf extern void charset_initialise(void); extern void codepage_initialise(int client_codepage); extern void TimeInit(void); extern int lp_load(const char *pszFname, int, int, int); extern void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]); #undef strcpy #undef strcat #ifdef __APPLE__ #define CONFIGFILE "/etc/smb.conf" #endif #ifndef CONFIGFILE #define CONFIGFILE "/etc/smb/smb.conf" #endif char *smb_crypt(const char *key, const char *salt); #endif /* USE_SMB */ extern char *optarg; extern int optind, opterr, optopt; void usage(char *name); void fatalError(char *name,char *str); void usage(char *name) { fprintf(stderr, "usage: %s [-s salt | -c cpass] [-qv] [mode] pass...\n",name); fprintf(stderr, "mode: crypt\n"); #ifdef USE_MD5 fprintf(stderr, "mode: -m md5\n"); #endif #ifdef USE_CRYPT16 fprintf(stderr, "mode: -l crypt16\n"); #endif #ifdef USE_BIGCRYPT fprintf(stderr, "mode: -b bigcrypt\n"); #endif #ifdef USE_SMB fprintf(stderr, "mode: -w LanManager/NT\n"); #endif exit(-1); } main(int argc, char **argv, char **envp) { char salts[]= "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789./"; int option; char optstring[64]="vqc:s:h"; char salt[32]; char *saltp=NULL; int quiet=0; int compare=0; int md5=0; int c16=0; int bc=0; int w=0; char *pass; char *cpass; char *(*my_crypt)(const char *key, const char *salt); struct timeval tp; #ifdef USE_SMB char *servicesf = CONFIGFILE; #endif #ifdef USE_MD5 strcat(optstring,"m"); #endif #ifdef USE_CRYPT16 strcat(optstring,"l"); #endif #ifdef USE_BIGCRYPT strcat(optstring,"b"); #endif #ifdef USE_SMB strcat(optstring,"w"); #endif my_crypt=&crypt; while(( option = getopt(argc, argv, optstring))!=EOF ) { switch(option) { #ifdef USE_MD5 case 'm': if ( c16|bc|w ) { fprintf(stderr,"Can't use both md5 and other modes\n"); exit(1); } md5=1; # if defined __linux__ my_crypt=&crypt; # else my_crypt=&__md5_crypt; # endif break; #endif #ifdef USE_CRYPT16 case 'l': if ( md5|bc|w ) { fprintf(stderr,"Can't use both crypt16 and other modes\n"); exit(1); } c16=1; my_crypt=&crypt16; break; #endif #ifdef USE_BIGCRYPT case 'b': if ( md5|c16|w ) { fprintf(stderr,"Can't use both bigcrypt and other modes\n"); exit(1); } bc=1; my_crypt=&bigcrypt; # if ( defined __osf__ ) && ( ! defined MY_BIGCRYPT ) set_auth_parameters(argc,argv); # endif break; #endif #ifdef USE_SMB case 'w': if ( md5|c16|bc ) { fprintf(stderr,"Can't use both NT and other modes\n"); exit(1); } w=1; my_crypt=&smb_crypt; TimeInit(); charset_initialise(); lp_load(servicesf,1,0,0); codepage_initialise(lp_client_code_page()); break; #endif case 'q': quiet=1; break; case 'c': compare=1; cpass=optarg; #ifdef USE_MD5 if (cpass[0]=='$') { md5=1; # if defined __linux__ my_crypt=&crypt; # else my_crypt=&__md5_crypt; # endif } #endif break; case 's': saltp=optarg; break; case 'v': fprintf(stderr,"%s\n",VERS_STR); break; default: usage(argv[0]); break; } } if ( compare && saltp ) usage(argv[0]); if (argv[optind]) { if (compare) { pass=my_crypt(argv[optind],cpass); if ( !quiet ) puts (pass) ; return( strcmp ( cpass, pass )); } else { if ( saltp == NULL ) { char *c; int i; saltp = salt; #if defined __SVR4 || defined _HPUX_SOURCE || defined __linux__ || defined __osf__ || defined __APPLE__ gettimeofday(&tp, NULL); #else gettimeofday(&tp); #endif srand( (unsigned int) tp.tv_usec ); #ifndef USE_MD5 salt[0] = *(salts+((long)rand() % (long)sizeof(salts))); salt[1] = *(salts+((long)rand() % (long)sizeof(salts))); #else if ( md5 ) { salt[0] = '$'; salt[1] = '1'; salt[2] = '$'; c = &salt[3]; for ( i=0; i<8; i++ ) *c++ = *(salts+((long)rand() % (long)sizeof(salts))); *c++ = 0x00; } else { salt[0] = *(salts+((long)rand() % (long)sizeof(salts))); salt[1] = *(salts+((long)rand() % (long)sizeof(salts))); } #endif } puts(my_crypt(argv[optind],saltp)); return (0); } } else { return(1); } } #ifdef MY_BIGCRYPT char *my_bigcrypt(const char *key, const char *salt) { #define BL 160 /* 2*AUTH_MAX_PASSWD_LENGTH */ static char c[BL]; static char k[AUTH_MAX_PASSWD_LENGTH+1]; char *p,*e; int l; k[AUTH_MAX_PASSWD_LENGTH]=0x00; strncpy(k,key,AUTH_MAX_PASSWD_LENGTH); l=strlen(k); strncpy(c,salt,2); c[2]=0x00; for(p=k; p 8) (void)strncpy(ttab, key+8, 8); ufc_mk_keytab(ttab); /* * Go for second 5 DES encryptions */ t = _ufc_doit((ufc_long)0, (ufc_long)0, (ufc_long)0, (ufc_long)0, (ufc_long)5); /* * And convert back to 6 bit ASCII */ strcpy (q, output_conversion(t[0], t[1], salt)); strcpy (res+13, q+2); clearmem(ktab, sizeof ktab); (void)strncpy(ktab, key, 8); ufc_mk_keytab(ktab); return res; } #endif #ifdef USE_SMB char *smb_crypt(const char *key, const char *salt) { /* salt is ignored */ static unsigned char nt_p16[16], p16[16]; static char nt_p32[33], p32[33]; static char p[66]; int i; memset(nt_p16, '\0', 16); memset(nt_p32, '\0', 33); memset(p16, '\0', 16); memset(p32, '\0', 33); nt_lm_owf_gen(key, nt_p16, p16); for( i = 0; i < 16; i++) { slprintf(&nt_p32[i*2], 3, "%02X", nt_p16[i]); slprintf(&p32[i*2], 3, "%02X", p16[i]); } strcpy(p,p32); strcat(p,":"); strcat(p,nt_p32); return p; } #endif