/* * kakumei_pass.h * * Password handling for kakumei. * * Author: Dario Rodriguez dario@softhome.net * This program is licensed under the terms of the Affero GPL v1+ */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "loglib.h" #include "kakumei.h" #include "libscrypt.h" #define VALUE_N 16384 #define VALUE_r 8 #define VALUE_p 1 static int mcf_gen(const char *salt,const char *passwd, char *mcf, int mcfsize); static int mcf_check(char *mcf, const char *passwd); int pass_new(kakumei *ka, char *user, char *passwd) { int fd; char filename[1024]; int len; int res; static const char mysalt[]={"NFkFsNdzMQ9Jfer"}; char mcf[SCRYPT_MCF_LEN]; if(kakumei_uservalid(ka,user)!=0) { log_write("PASS","Ilegal username %s",user); return(-1); } memset(mcf,0,sizeof(mcf)); if((res=mcf_gen(mysalt,passwd,mcf,sizeof(mcf)))!=0) { log_write("PASS","Couln't create simple hash for user %s",user); return(-1); } if((res=mcf_check(mcf,passwd))!=0) { log_write("EINT","%s:%i",__FILE__,__LINE__); return(-1); /* internal error */ } mkdir(DATADIR,0700); mkdir(USERSDIR,0700); snprintf(filename,sizeof(filename)-1,"%s/%s",USERSDIR,user); filename[sizeof(filename)-1]='\0'; mkdir(filename,0700); snprintf(filename,sizeof(filename)-1,"%s/%s/passwd",USERSDIR,user); filename[sizeof(filename)-1]='\0'; if((fd=open(filename,O_WRONLY|O_TRUNC|O_CREAT,0600))==-1) { log_write("PASS","Couln't open for writing to %s",filename); return(-1); } len=strlen(mcf); if(write(fd,mcf,len)!=len) { close(fd),fd=-1; log_write("PASS","Error writing to %s",filename); return(-1); } close(fd),fd=-1; return(0); } int pass_check(kakumei *ka, char *user, char *passwd) { int fd; char filename[1024]; char mcf[SCRYPT_MCF_LEN]; int res; if(kakumei_userexists(ka,user)!=0) { log_write("PASS","No username %s",user); return(-1); } snprintf(filename,sizeof(filename)-1,"%s/%s/passwd",USERSDIR,user); filename[sizeof(filename)-1]='\0'; if((fd=open(filename,O_RDONLY))==-1) { log_write("PASS","Couldn't read passwd of user %s",user); return(-1); } memset(mcf,0,sizeof(mcf)); read(fd,mcf,sizeof(mcf)-1); close(fd),fd=-1; if((res=mcf_check(mcf,passwd))!=0) { log_write("PASS","Wrong password trying to login for user %s",user); return(-1); } return(0); } /* utility functions to make libscrypt usable */ static int mcf_gen(const char *salt,const char *passwd, char *mcf, int mcfsize) { int res; uint8_t hashbuf[SCRYPT_HASH_LEN]; char saltbuf[1024]; char outbuf[1024]; if(mcfsize<SCRYPT_MCF_LEN) return(-1); if(strlen(salt)>16) return(-1); /* large salts make libscrypt break */ if((res=libscrypt_scrypt((uint8_t*)passwd,strlen(passwd), (uint8_t*)salt, strlen(salt), VALUE_N,VALUE_r,VALUE_p, hashbuf, sizeof(hashbuf)))!=0) { log_write("PASS","Couln't create hash"); return(-1); } if((res=libscrypt_b64_encode(outbuf, (char*)hashbuf, sizeof(hashbuf)))==-1) { log_write("PASS","Couln't encode hash"); return(-1); } if((res=libscrypt_b64_encode(saltbuf, salt, strlen(salt)))==-1) { log_write("PASS","Couln't encode salt"); return(-1); } if(!(res=libscrypt_mcf(VALUE_N,VALUE_r,VALUE_p, saltbuf, outbuf, mcf))) { log_write("PASS","Couln't convert to mcf"); return(-1); } return(0); } static int mcf_check(char *mcf, const char *passwd) { char mcftest[SCRYPT_MCF_LEN]; int res; memcpy(mcftest,mcf,sizeof(mcftest)); if((res=libscrypt_check(mcftest,(char *)passwd))<=0) return(-1); return(0); }