Path: blob/main/crypto/krb5/src/lib/kadm5/chpass_util.c
39536 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/*2* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.3*/456#include "k5-int.h"78#include <kadm5/admin.h>9#include "admin_internal.h"101112#define string_text error_message1314/*15* Function: kadm5_chpass_principal_util16*17* Purpose: Wrapper around chpass_principal. We can read new pw, change pw and return useful messages18*19* Arguments:20*21* princ (input) a krb5b_principal structure for the22* principal whose password we should change.23*24* new_password (input) NULL or a null terminated string with the25* the principal's desired new password. If new_password26* is NULL then this routine will read a new password.27*28* pw_ret (output) if non-NULL, points to a static buffer29* containing the new password (if password is prompted30* internally), or to the new_password argument (if31* that is non-NULL). If the former, then the buffer32* is only valid until the next call to the function,33* and the caller should be sure to zero it when34* it is no longer needed.35*36* msg_ret (output) a useful message is copied here.37*38* <return value> exit status of 0 for success, else the com err code39* for the last significant routine called.40*41* Requires:42*43* A msg_ret should point to a buffer large enough for the messasge.44*45* Effects:46*47* Modifies:48*49*50*/5152kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,53void *lhandle,54krb5_principal princ,55char *new_pw,56char **ret_pw,57char *msg_ret,58unsigned int msg_len)59{60int code, code2;61unsigned int pwsize;62static char buffer[255];63char *new_password;64kadm5_principal_ent_rec princ_ent;65kadm5_policy_ent_rec policy_ent;6667_KADM5_CHECK_HANDLE(server_handle);6869if (ret_pw)70*ret_pw = NULL;7172if (new_pw != NULL) {73new_password = new_pw;74} else { /* read the password */75krb5_context context;7677if ((code = (int) kadm5_init_krb5_context(&context)) == 0) {78pwsize = sizeof(buffer);79code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT,80KADM5_PW_SECOND_PROMPT,81buffer, &pwsize);82krb5_free_context(context);83}8485if (code == 0)86new_password = buffer;87else {88#ifdef ZEROPASSWD89memset(buffer, 0, sizeof(buffer));90#endif91if (code == KRB5_LIBOS_BADPWDMATCH) {92strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),93msg_len - 1);94msg_ret[msg_len - 1] = '\0';95return(code);96} else {97snprintf(msg_ret, msg_len, "%s %s\n\n%s",98error_message(code),99string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),100string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));101msg_ret[msg_len - 1] = '\0';102return(code);103}104}105if (pwsize == 0) {106#ifdef ZEROPASSWD107memset(buffer, 0, sizeof(buffer));108#endif109strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1);110msg_ret[msg_len - 1] = '\0';111return(KRB5_LIBOS_CANTREADPWD); /* could do better */112}113}114115if (ret_pw)116*ret_pw = new_password;117118code = kadm5_chpass_principal(server_handle, princ, new_password);119120#ifdef ZEROPASSWD121if (!ret_pw)122memset(buffer, 0, sizeof(buffer)); /* in case we read a new password */123#endif124125if (code == KADM5_OK) {126strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1);127msg_ret[msg_len - 1] = '\0';128return(0);129}130131if ((code != KADM5_PASS_Q_TOOSHORT) &&132(code != KADM5_PASS_REUSE) &&(code != KADM5_PASS_Q_CLASS) &&133(code != KADM5_PASS_Q_DICT) && (code != KADM5_PASS_TOOSOON)) {134/* Can't get more info for other errors */135snprintf(msg_ret, msg_len, "%s\n%s %s\n",136string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),137error_message(code),138string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));139return(code);140}141142/* Ok, we have a password quality error. Return a good message */143144if (code == KADM5_PASS_REUSE) {145strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1);146msg_ret[msg_len - 1] = '\0';147return(code);148}149150if (code == KADM5_PASS_Q_DICT) {151strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY),152msg_len - 1);153msg_ret[msg_len - 1] = '\0';154return(code);155}156157/* Look up policy for the remaining messages */158159code2 = kadm5_get_principal (lhandle, princ, &princ_ent,160KADM5_PRINCIPAL_NORMAL_MASK);161if (code2 != 0) {162snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n",163error_message(code2),164string_text(CHPASS_UTIL_GET_PRINC_INFO),165error_message(code),166string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),167string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));168msg_ret[msg_len - 1] = '\0';169return(code);170}171172if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) {173/* Some module implements its own password policy. */174snprintf(msg_ret, msg_len, "%s\n\n%s",175error_message(code),176string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));177msg_ret[msg_len - 1] = '\0';178(void) kadm5_free_principal_ent(lhandle, &princ_ent);179return(code);180}181182code2 = kadm5_get_policy(lhandle, princ_ent.policy,183&policy_ent);184if (code2 != 0) {185snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n ", error_message(code2),186string_text(CHPASS_UTIL_GET_POLICY_INFO),187error_message(code),188string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),189string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));190(void) kadm5_free_principal_ent(lhandle, &princ_ent);191return(code);192}193194if (code == KADM5_PASS_Q_TOOSHORT) {195snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT),196policy_ent.pw_min_length);197(void) kadm5_free_principal_ent(lhandle, &princ_ent);198(void) kadm5_free_policy_ent(lhandle, &policy_ent);199return(code);200}201202/* Can't get more info for other errors */203204if (code == KADM5_PASS_Q_CLASS) {205snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_TOO_FEW_CLASSES),206policy_ent.pw_min_classes);207(void) kadm5_free_principal_ent(lhandle, &princ_ent);208(void) kadm5_free_policy_ent(lhandle, &policy_ent);209return(code);210}211212if (code == KADM5_PASS_TOOSOON) {213time_t until;214char *time_string, *ptr;215216until = ts_incr(princ_ent.last_pwd_change, policy_ent.pw_min_life);217218time_string = ctime(&until);219if (time_string == NULL)220time_string = "(error)";221else if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')222*ptr = '\0';223224snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SOON),225time_string);226(void) kadm5_free_principal_ent(lhandle, &princ_ent);227(void) kadm5_free_policy_ent(lhandle, &policy_ent);228return(code);229}230231/* We should never get here, but just in case ... */232snprintf(msg_ret, msg_len, "%s\n%s %s\n",233string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),234error_message(code),235string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));236(void) kadm5_free_principal_ent(lhandle, &princ_ent);237(void) kadm5_free_policy_ent(lhandle, &policy_ent);238return(code);239}240241242