📄 passwd.c
字号:
DO_ERROR("Warning, shell not in /etc/shells\n"); } else DO_EXIT("Invalid shell selection, shell unchanged.\n", 1); } if (access(shell, X_OK) < 0) { char buf[MAXPATHLEN+50]; strcpy(buf, shell); strcat(buf, " is unavailable.\n"); DO_EXIT(buf, 1); } if(!strcmp(shell, DEFSHELL)) strcpy(shell, ""); pwd->pw_shell = shell; if(storepwent(pwd)) { DO_EXIT("Shell not changed.\n", 1); } else audevent("Shell successfully changed.", 0); } if(fopt) { char *name, *office, *ophone, *hphone; char newname[ENTRY_SIZE], newoffice[ENTRY_SIZE], newophone[ENTRY_SIZE], newhphone[ENTRY_SIZE]; char line[1024]; fputs("Changing finger information for ", stdout); puts(pwd->pw_name); name = office = ophone = hphone = ""; name = pwd->pw_gecos; if(name) { office = strpbrk(name, ",:\n"); if(office) { if(*office == ',') { *office = '\0'; office++; ophone = strpbrk(office, ",:\n"); if(ophone) { if(*ophone == ',') { *ophone = '\0'; ophone++; hphone = strpbrk(ophone, ",:\n"); if(hphone) { if(*hphone == ',') { *hphone = '\0'; hphone++; } } else hphone = ""; } } else ophone = ""; } } else office = ""; } name = getentry("Name", name, newname, ENTRY_SIZE); office = getentry("Office number", office, newoffice, ENTRY_SIZE); ophone = getentry("Office Phone", ophone, newophone, ENTRY_SIZE); hphone = getentry("Home Phone", hphone, newhphone, ENTRY_SIZE); sprintf(line, "%s,%s,%s,%s", name, office, ophone, hphone); pwd->pw_gecos = line; if(storepwent(pwd)) { DO_EXIT("Finger information not changed.\n", 1); } else audevent("Finger information successfully changed.", 0); } if(!sopt && !fopt) { if (!eopt) { fputs("Changing password for ", stdout); puts(pwd->pw_name); } umask(077); now = time((long *) 0);/* If we are running with C2 or less security look for the password first in the passwd data base.*/ if(sec_level >= SEC_UPGRADE) {/* Open the auth file and get the users auth entry using their UID as the key.*/ auth = getauthuid(user_id); if(auth == (AUTHORIZATION *) NULL && root == 2) auth = getauthuid_hesiod(user_id); if(auth == (AUTHORIZATION *) NULL) { char buf[256]; sprintf(&buf[0], "Unable to retrieve auth information for %s.\n", user_name); DO_EXIT(&buf[0], 2); } } else auth = (AUTHORIZATION *) NULL; if(ypuid && (sec_level == SEC_ENHANCED)) { /* wierd case: Yp served uid at ENHANCED level */ hesflg=1; /* Assume hesiod served auth */ if(root) root=2; }/* Retrieve old encrypted password.*/ if(sec_level == SEC_BSD || sec_level <= SEC_UPGRADE && pwd->pw_passwd && strcmp(pwd->pw_passwd, "*")) strncpy(crypt_pass, pwd->pw_passwd, sizeof crypt_pass); else strncpy(crypt_pass, auth->a_password, sizeof crypt_pass);/* If the invoker is not privileged (SSO or ROOT) require re-authentication, verify that they have CHANGE_PASSWORD privilege, and check the minimum expiration time.*/ if(!priv) {/* Check CHANGE_PASSWORD privilege.*/ if(auth && !(auth->a_authmask & A_CHANGE_PASSWORD)) DO_EXIT("You do not have the privilege to change your password.\n", 1); }/* Check minimum password expiration time.*/ if(!priv && auth) { deadline = auth->a_pass_mod; period = auth->a_pw_minexp; deadline += period; if(now < deadline) DO_EXIT("Sorry, the minimum password lifetime has not expired yet.\n", 1); }/* Reauthenticate.*/ if(!priv && *crypt_pass) { strncpy(salt, crypt_pass, 2); salt[2] = '\0'; s = getpass("Old password: "); strncpy(old_pass, s, sizeof (PASSWORD)); old_pass[MAX_PASSWORD_LENGTH] = '\0'; putchar('\n'); if(sec_level == SEC_BSD || sec_level <= SEC_UPGRADE && pwd->pw_passwd && strcmp(pwd->pw_passwd, "*")) cp = crypt(old_pass, salt); else cp = crypt16(old_pass, salt); if(!hesflg) bzero(old_pass, sizeof old_pass); if(strcmp(crypt_pass, cp)) { audevent("Failed authentication", 1); sleep(2); puts("Sorry"); exit(1); } }/* * The current prompter protocol does not support reauthentication; this * forces 'passwd -e' to be invokable only by root and to kludge the use of * priv when in extended protocol mode. This has the side affect of including * root in further checks if 'passwd -e root'. */ if (eopt) { priv = 0; }/* Get the new password.*/ if(!auth) { max_pw_len = 8; if(min_pw_len > max_pw_len) min_pw_len = max_pw_len; } else if(!priv && !(auth->a_authmask & A_ENTER_PASSWORD)) aopt = 1; if (eopt) { static REQ request; REQ *req = &request; LISTOFPAIRS pairs; LISTOFPAIRS *pair_list = &pairs; LISTOFPASSWORDS *passwd_list = (LISTOFPASSWORDS *)req->data; int length; makeseed(&i, 4); srandom(i); /* Get password */ do { bzero(pair_list, sizeof(LISTOFPAIRS)); pair_list->count = RANDOM_WORDS; for(i=0; i < RANDOM_WORDS; i++) { randomword(pair_list->pairs[i].passwd.data, pair_list->pairs[i].phonetic.data, min_pw_len, max_pw_len, 0); pair_list->pairs[i].passwd.length = strlen(pair_list->pairs[i].passwd.data); pair_list->pairs[i].phonetic.length = strlen(pair_list->pairs[i].phonetic.data); } SENDREQ(req, CHZPWD, pair_list, sizeof(LISTOFPAIRS)); again: SENDREQ(req, GETPWD, (char *)0, 0); GETREQ(req, i); if(i <= 0) exit(2); if (req->opcode != PASSWD) { DO_ERROR("Did not receive PASSWD request.\n"); goto again; } if (passwd_list->count && auth && !(auth->a_authmask & A_ENTER_PASSWORD)) { for (i=0; i < RANDOM_WORDS; i++) { if (!strcmp(passwd_list->passwords[0].data, pair_list->pairs[i].passwd.data)) break; } if(i >= RANDOM_WORDS) { DO_ERROR("You must select from the list shown.\n"); goto again; } } } while (passwd_list->count == 0); /* Save password and verify string */ length = passwd_list->passwords[0].length; if(length > MAX_PASSWORD_LENGTH) length = MAX_PASSWORD_LENGTH; strncpy(new_pass, passwd_list->passwords[0].data, length); new_pass[length] = '\0'; length = passwd_list->passwords[1].length; if(length > MAX_PASSWORD_LENGTH) length = MAX_PASSWORD_LENGTH; strncpy(verify, passwd_list->passwords[1].data, length); s = (unsigned char *) passwd_list->passwords[0].data; /* Clear temp space */ bzero(pair_list, sizeof(LISTOFPAIRS)); } else if (aopt) { makeseed(&i, 4); srandom(i); do { puts("Here are some suggested passwords:\n"); for(i=0; i < NUM_CHOICES; i++) { randomword(gen_password[i], hyph_password, min_pw_len, max_pw_len, 0); printf("%-16s %-16s\n", gen_password[i], hyph_password); } s = getpass("\nEnter new password: "); strncpy(new_pass, s, sizeof (PASSWORD)); new_pass[MAX_PASSWORD_LENGTH] = '\0'; putchar('\n'); if(!priv && *new_pass && auth && !(auth->a_authmask & A_ENTER_PASSWORD)) { for(i=0; i < NUM_CHOICES; i++) { if(!strcmp(new_pass, gen_password[i])) break; } if(i >= NUM_CHOICES) { new_pass[0] = '\0'; DO_ERROR("You must select from the list shown.\n"); } else break; } } while(strlen(new_pass) == 0); } else { s = getpass("Enter new password: "); strncpy(new_pass, s, sizeof (PASSWORD)); new_pass[MAX_PASSWORD_LENGTH] = '\0'; putchar('\n'); }/* Check password length.*/ if(!*new_pass) DO_EXIT("Password unchanged.\n", 1); if((i=strlen(s)) < min_pw_len) { char buf[256]; bzero(new_pass, sizeof new_pass); sprintf(&buf[0], "Password must be at least %d characters long, password unchanged.\n", min_pw_len); DO_EXIT(&buf[0], 1); } if(i > max_pw_len) { char buf[256]; new_pass[max_pw_len] = '\0'; if(sec_level <= SEC_BSD) sprintf(&buf[0], "Warning, only the first %d characters of the password are significant.\n", max_pw_len); else { sprintf(&buf[0], "%s, your password cannot be longer than %d characters.\n", eopt?"Error":"Warning", max_pw_len); if(eopt) DO_EXIT(&buf[0], 1); } DO_ERROR(&buf[0]); }/* If the user is not privileged check to make sure their password meets some minimal requirements.*/ if(!priv) {/* Make sure new password is not the same as old password.*/ if(*crypt_pass) { salt[0] = crypt_pass[0]; salt[1] = crypt_pass[1]; salt[2] = '\0'; if(auth) cp = crypt16(new_pass, salt); else cp = crypt(new_pass, salt); if(!strcmp(crypt_pass, cp)) { bzero(new_pass, sizeof new_pass); DO_EXIT("Password is not different enough, unchanged.\n", 1); } }/* Make sure the password does not equal the logname.*/ cp2 = new_pass; cp = pwd->pw_name; for(cp2=new_pass, cp=pwd->pw_name; *cp2 && *cp; cp2++, cp++) if(lcase(*cp) != lcase(*cp2)) break; if(lcase(*cp) == lcase(*cp2)) DO_EXIT("Password must be different than logname.\n", 1);#ifdef CHECKCHARS/* Make sure password uses a rich enough character set.*/ for(cp2=new_pass; *cp2; cp2++) chartab[*cp2]++; for(i=0; i < sizeof chartab; i++) if(chartab[i]) charset++; if(charset < CHECKCHARS) { char buf[256]; bzero(new_pass, sizeof new_pass); bzero(chartab, sizeof chartab); charset = 0; sprintf(&buf[0], "Password must contain at least %d different characters.\n", CHECKCHARS); DO_EXIT(&buf[0], 1); }#endif }/* Verify password to prevent typos.*/ if (!eopt) { s = getpass("Verify: "); strncpy(verify, s, sizeof (PASSWORD)); verify[MAX_PASSWORD_LENGTH] = '\0'; putchar('\n'); if((i=strlen(verify)) > max_pw_len) if(sec_level > SEC_BSD) { DO_EXIT("Error, password too long.\n", 1); } else verify[max_pw_len] = '\0'; } if(strcmp(new_pass, verify)) DO_EXIT("Verification failed, password unchanged.\n", 1); bzero(verify, sizeof verify);/* Encrypt and store the new password.*/ srandom(time(0)); salt[0] = salt_table[random() % 64]; salt[1] = salt_table[random() % 64]; if(sec_level == SEC_BSD || !auth) pwd->pw_passwd = crypt(new_pass, salt); else bcopy(crypt16(new_pass, salt), auth->a_password, CRYPT_PASSWORD_LENGTH); bzero(new_pass, sizeof new_pass);/* If the user is privileged set the expiration periods.*/#ifdef XYZ if(!eopt && priv && auth) {/* Set the maximum expiration period.*/ printf("Enter expiration period in days (RET for %1d, 0 for none): ", DEF_EXP_PERIOD/60/60/24); fgets(string, sizeof string, stdin); if(string[0] == '\n') period = DEF_EXP_PERIOD; else period = atoi(string)*60*60*24; auth->a_pw_maxexp = period;/* Set the minimum expiration period.*/ fputs("Enter minimum password lifetime in minutes (RET for 0): ", stdout); fgets(string, sizeof string, stdin); if(string[0] == '\n') period = 0; else period = atoi(string)*60; auth->a_pw_minexp = period; }#endif/************************************************************************//* *//* The hesupd call processing *//* *//************************************************************************/ if(hesflg) { signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); (void) umask(0); bzero((char *)&hupmsg, sizeof(struct hesupdmsg)); strcpy(hupmsg.oldpwd,old_pass); hupmsg.hesuid = pwd->pw_uid; hupmsg.opcode=PASSCHG; if(auth) strcpy(hupmsg.newcrypt,auth->a_password); else strcpy(hupmsg.newcrypt,pwd->pw_passwd); if(hupdtp(&hupmsg)) { DO_EXIT("Your distributed password is updated\n", 0); } else { DO_EXIT("Your distributed password has not been changed\n", 2); } exit(0); /*****end of hesupd processing*********/ } if(auth) {/* Set the password modification time to now and store the new auth entry.*/ auth->a_pass_mod = now; if(storeauthent(auth)) DO_EXIT("Unable to set new password.\n", 2); endauthent(); if(gp=getgrnam("authread")) auth_gid = gp->gr_gid; else auth_gid = 9; if(our_id == 0) i = chown(AUTHORIZATION_DB, sso_id, auth_gid); else i = chown(AUTHORIZATION_DB, -1, auth_gid); if(i >= 0) chmod(AUTHORIZATION_DB, 0640); if(strcmp(passave, "*")) { pwd->pw_passwd = "*"; umask(022); if(storepwent(pwd)) DO_EXIT("Unable to change passwd file.\n", 2); } } else { umask(022); if(storepwent(pwd)) DO_EXIT("Unable to set password.\n", 2); } if(aopt && !eopt) DO_ERROR("Remember to destroy any printed passwords.\n"); audevent("Password successfully changed.", 0); } exit(0);}/************************************************************************//* *//* hesupd transaction processing module *//* *//************************************************************************/inthupdtp(hup) struct hesupdmsg *hup;{ static struct sockaddr sock, sock2; struct hostent *hp; char host[34]; struct sockaddr_in sin; struct servent *sp; /* service spec for tcp/hesupd */ int hlen = 32; int net, socklen, amount, i, t, j, retmsg=HESUPDNAK; int ans, port, retry; /* first check to see if we are the bind master */ gethostname(host,hlen); hp = gethostbyname(bindmaster); if(hp == 0) return(0); /* cant lookup the bindmaster hostname */ if(!strcmp(host,hp->h_name) && root == 2 ) { /* bingo - I am root and this is the bindmaster */ if (chdir(homebase) < 0) { fprintf(stderr, "passwd can't chdir to %s\n",homebase); return(0); } switch(svcp->svcauth.seclevel) { case SEC_BSD: return(chpw_bsd(hup->hesuid,hup->oldpwd,hup->newcrypt)); case SEC_UPGRADE: return(chpw_upgrade(hup->hesuid,hup->oldpwd,hup->newcrypt)); case SEC_ENHANCED: return(chpw_enhanced(hup->hesuid,hup->oldpwd,hup->newcrypt)); } } mix(hup); /***** *****/ /***** Get port number of hesupd *****/ /***** *****/ sp=getservbyname("hesupd","tcp"); if (sp == 0) { DO_ERROR("hesupd/tcp: unknown service\n"); return(0); } /***** *****/ /***** Get Bind master hostname *****/ /***** *****/ hp = gethostbyname(bindmaster); if (hp == NULL) { DO_ERROR("No registered hesiod master\n"); return(0); } /***** *****/ /***** Setup the socket *****/ /***** *****/ bzero((char *)&sin, sizeof (sin)); bcopy(hp->h_addr,(char *)&sin.sin_addr, hp->h_length);/* Save the remote address for auditing *//* bcopy(hp->h_addr, remote_hostaddr.sa_data, sizeof (long)); remote_hostaddr.sa_family = hp->h_addrtype; remote_hostflag = 1;*/ sin.sin_family = hp->h_addrtype; sin.sin_port = sp->s_port; /***** *****/ /***** Try HESRETRY times to connect to hesupd *****/ /***** *****/ for(retry=HESRETRY; retry != 0; retry-- ) { net = socket(AF_INET, SOCK_STREAM, 0); if (net < 0) { DO_ERROR("hesupd: socket error\n"); return(0); } /***** *****/ /***** Make connection to Hesupd *****/ /***** *****/ if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { (void) close(net); net = -1; continue; } /***** *****/ /***** Send out hesupd message *****/ /***** *****/ amount = send(net, (char *) hup, sizeof(struct hesupdmsg), 0); if(amount < sizeof(struct hesupdmsg)) { (void) close(net); DO_ERROR("hesupd send error\n"); return(0); } /***** *****/ /***** Receive Ack or Nak from Hesupd *****/ /***** This will hang if hesupd dies *****/ /***** *****/ amount = recv(net, (char *)&retmsg, sizeof(retmsg), 0); if(amount < sizeof(retmsg)) { (void) close(net); DO_ERROR("hesupd recv error\n"); return(0); } else break; } (void) close(net); net = -1; if(retmsg == HESUPDACK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -