#include "shared_encrypt.h" #ifdef ENCRYPT_PASSWORDS /* #defined in custom.h */ static char des_salt_char(char letter) { /* salt_string contains the characters which may be used as a ** crypt() salt */ char *salt_string = "aA0bBcC1dDe2EfF3gGh4H.I5iJ6jK7k8L9lMmNnOo/PpqQrRsStTuUVvWwxXYyZz"; return *(salt_string + (letter % 64)); /* 64 is the length of salt_string above */ } /* returns a two character DES salt string ** - take the first two chars of username as a salt ** - use it to encrypt the username ** - return chars 5 and 11 of the encrypted username as the ** salt **/ static char *des_salt(const char *username) { static char salt[3]; char encrypted_username[MAX_ENCRYPTED_PASSWORD + 1]; if(strlen(username) >= 2) /* this should always be the case */ { *salt = des_salt_char(*username); *(salt + 1) = des_salt_char(*(username + 1)); *(salt + 2) = '\0'; } else strcpy(salt, "x4"); /* should never get to that point */ strncpy(encrypted_username, crypt(username, salt), MAX_ENCRYPTED_PASSWORD + 1); if(strlen(encrypted_username) >= 12) { *salt = des_salt_char(encrypted_username[5]); *(salt + 1) = des_salt_char(encrypted_username[11]); *(salt + 2) = '\0'; } return salt; } /** returns the last 8 chars of string **/ static char *last_eight_chars(const char *string) { int len; static char last_eight[9]; len = strlen(string); if(len <= 8) strcpy(last_eight, string); else strcpy(last_eight, string + len - 8); return last_eight; } static char *md5_salt(const char *username) { static char salt[MAX_SALT + 1]; char encrypted_username[MAX_ENCRYPTED_PASSWORD + 1]; char tmp_salt[MAX_SALT + 1]; char *ptr; strncpy(encrypted_username, crypt(username, des_salt(username)), MAX_ENCRYPTED_PASSWORD + 1); strncpy(tmp_salt, last_eight_chars(encrypted_username), MAX_SALT + 1); for(ptr = tmp_salt; *ptr; ptr++) *ptr = des_salt_char(*ptr); strcpy(salt,"$1$"); strcat(salt, tmp_salt); strcat(salt, "$"); return salt; } static char *my_salt(const char *username) { if(USE_MD5_ENCRYPTION) return md5_salt(username); else return des_salt(username); } char *encrypted_password(const char *plaintext_password, const char *username) { return crypt(plaintext_password, my_salt(username)); } #else /***************** no encryption version *******************/ char *encrypted_password(const char *plaintext_password, const char *username) { static char the_password[MAX_ENCRYPTED_PASSWORD + 1]; strncpy(the_password, plaintext_password, MAX_ENCRYPTED_PASSWORD + 1); return the_password; } #endif void create_admin_user_dir(char *username, char *plaintext_passwd, ADMIN_CONFIG_STRUCT *conf) { char dir_name[MAX_PATH +1]; FILE *fp; struct stat buf; /* create 'keys' directory, if it doesn't exist */ snprintf(dir_name, MAX_PATH+1, "../%s/%s/%s", USERS_DIR, ADMIN_DIR, KEY_DIR); if(stat(dir_name, &buf) != 0) { if(mkdir(dir_name, 0770) == -1) cs_critical_error( ERR_MKDIR_FAILED, ""); } /* create 'survey' directory, if it doesn't exist */ /* snprintf(dir_name, MAX_PATH+1, "../%s/%s/%s", USERS_DIR, ADMIN_DIR, SURVEY_DIR); if(stat(dir_name, &buf) != 0) { if(mkdir(dir_name, 0770) == -1) cs_critical_error( ERR_MKDIR_FAILED, ""); } */ /* create the 'letter' dir for this user, if it doesn't exist */ snprintf(dir_name, MAX_PATH+1, "../%s/%s/%c", USERS_DIR, ADMIN_DIR,sub_dir_name(username)); /* shared_authenticate.c */ if(stat(dir_name, &buf) != 0) { if(mkdir(dir_name, 0770) == -1) cs_critical_error( ERR_MKDIR_FAILED, ""); } /* create the username directory for this user */ snprintf(dir_name, MAX_PATH +1, "../%s/%s/%c/%s", USERS_DIR, ADMIN_DIR, sub_dir_name(username), username); if(mkdir(dir_name, 0770) == -1) cs_critical_error( ERR_MKDIR_FAILED, ""); /* write the password file */ snprintf(dir_name, MAX_PATH +1, "../%s/%s/%c/%s/%s", USERS_DIR, ADMIN_DIR, sub_dir_name(username), username, PASSWD_FNAME); fp = fopen(dir_name, "w"); if(!fp) cs_critical_error( ERR_FOPEN_WRITE_FAILED, ""); fputs(encrypted_password(plaintext_passwd ,username), fp); fclose(fp); /* write the configuration file */ write_super_configuration_file(username, conf); /* shared_super_util.c */ } /*** returns via encrypted_password, the encrypted password for the **** administrator identified by username. *** Returns 0 on failure , 1 on success **/ int get_super_user_password (const char *username, char *encrypted_password) { char path[MAX_PATH +1]; char line[200]; FILE *fp; snprintf(path, MAX_PATH +1, "../%s/%s/%c/%s/%s", USERS_DIR, ADMIN_DIR, sub_dir_name(username), username, PASSWD_FNAME); fp = fopen(path, "r"); if(!fp) return 0; if(!fgets(line, 200, fp)) { fclose(fp); return 0; } fclose(fp); strtrm(line); /* shared_strtrm.c */ strncpy(encrypted_password, line, MAX_ENCRYPTED_PASSWORD + 1); *(encrypted_password + MAX_ENCRYPTED_PASSWORD) = '\0'; return 1; } /** Does the plaintext_passwd provided by the administrator username *** match the encrypted password for that user? **/ int confirm_super_password(const char *plaintext_passwd, const char *username) { char correct_password[MAX_ENCRYPTED_PASSWORD + 1]; return get_super_user_password (username, correct_password) && !strcmp(correct_password, encrypted_password(plaintext_passwd, username)) ; } int get_central_user_password (const char *username, char *encrypted_password) { FILE *fp; char line[200]; char passwd_fname[MAX_PATH + 1]; char dir; dir = sub_dir_name(username); snprintf(passwd_fname, MAX_PATH + 1, "../%s/%c/%s/%s", USERS_DIR, dir, username,PASSWD_FNAME); fp = fopen(passwd_fname,"r"); if(!fp) return 0; if(!fgets(line,200,fp)) { fclose(fp); return 0; } fclose(fp); strtrm(line); /*shared_strtrm.c */ strncpy(encrypted_password,line,MAX_ENCRYPTED_PASSWORD + 1); return 1; } int write_central_password_file (const char *username, const char *plaintext_password) { char passwd_fname[MAX_PATH + 1]; FILE *fp; char dir; dir = sub_dir_name(username); snprintf(passwd_fname, MAX_PATH + 1, "../%s/%c/%s/%s", USERS_DIR, dir, username, PASSWD_FNAME); fp = fopen(passwd_fname, "w"); if(!fp) return 0; fputs(encrypted_password(plaintext_password, username), fp); /* shared_encrypt.c */ fclose(fp); return 1; } USER_STATUS record_central_user_info(USER_STATUS status, const char *realname, const char *username, const char *password, const char *id, const char *crs) { char user_dir[MAX_PATH + 1]; if(status == NEW_USER) { if(!create_central_letter_dir (sub_dir_name(username))) /*sub_dir_name() is in shared_authenticate.c */ return ERROR; if(!create_central_user_dir (username)) return ERROR; if(!write_central_password_file (username, password)) return ERROR; if(!write_central_id_file (realname,username,id)) return ERROR; sprintf(user_dir,"../%s", USERS_DIR); if(!add_to_user_index(user_dir, username, realname, id)) /*shared_user_index.c*/ return ERROR; } /* next for both new and existing users */ if(!update_central_course_file(username,crs)) /* shared_add_util.c */ return ERROR; return status; } int update_central_user ( const char *first, const char *last, const char *id, const char * crs, const char *realname, char *username, char *plaintext_password) { int try,done; USER_STATUS status; int user_len; derive_username(first, last, id, username, MAX_USERNAME + 1); /* shared_authenticate.c */ user_len = strlen (username); for(try = 0, done = 0; !done && (try < MAX_USERNAME_TRIES); try++) /* MAX_USERNAME_TRIES is in shared_authenticate.h */ { status = check_central_username (username,id); switch (status) { case NEW_USER: case EXISTING_USER: done = 1; derive_password (username, first, last, id, plaintext_password, MAX_PASSWORD); /* shared_authenticate.c */ if(record_central_user_info(status, realname, username, plaintext_password, id, crs) == ERROR) return 0; break; default: derive_another_username(first, last,id,username,MAX_USERNAME + 1, try + 1); break; } } if (!done) return 0; else return 1; } int write_password (const char *username, const char *plaintext_password, const char *course_path) { FILE *fp; char passwd_path[MAX_PATH + 1]; snprintf(passwd_path, MAX_PATH + 1, "%s%s%s/%s/%s",course_path, strlen(course_path)?"/":"", PEOPLE_DIR, username,PASSWORD_FNAME); fp = fopen (passwd_path,"w"); if(!fp) return 0; if(get_exclusive_lock(fileno(fp), 0)) /* shared_lock.c */ { fclose(fp); return 0; } fputs(encrypted_password(plaintext_password, username), fp); /* shared_encrypt.c */ release_lock(fileno(fp)); /* shared_lock.c */ fclose(fp); return 1; }