afs_int32 ka_GetAuthToken(char *name, char *instance, char *cell, struct ktc_encryptionKey * key, afs_int32 lifetime, afs_int32 * pwexpires) { afs_int32 code; struct ubik_client *conn; afs_int32 now = time(0); struct ktc_token token; char cellname[MAXKTCREALMLEN]; char realm[MAXKTCREALMLEN]; struct ktc_principal client, server; LOCK_GLOBAL_MUTEX; code = ka_ExpandCell(cell, cellname, 0 /*local */ ); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } cell = cellname; /* get an unauthenticated connection to desired cell */ code = ka_AuthServerConn(cell, KA_AUTHENTICATION_SERVICE, 0, &conn); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } code = ka_Authenticate(name, instance, cell, conn, KA_TICKET_GRANTING_SERVICE, key, now, now + lifetime, &token, pwexpires); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } code = ubik_ClientDestroy(conn); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } code = ka_CellToRealm(cell, realm, 0 /*local */ ); if (code) { UNLOCK_GLOBAL_MUTEX; return code; } strcpy(client.name, name); strcpy(client.instance, instance); strncpy(client.cell, cell, sizeof(client.cell)); strcpy(server.name, KA_TGS_NAME); strcpy(server.instance, realm); strcpy(server.cell, cell); code = ktc_SetToken(&server, &token, &client, 0); UNLOCK_GLOBAL_MUTEX; return code; }
int CommandProc(struct cmd_syndesc *as, void *arock) { char name[MAXKTCNAMELEN] = ""; char instance[MAXKTCNAMELEN] = ""; char cell[MAXKTCREALMLEN] = ""; char realm[MAXKTCREALMLEN] = ""; afs_int32 serverList[MAXSERVERS]; char *lcell; /* local cellname */ int code; int i; struct ubik_client *conn = 0; struct ktc_encryptionKey key; struct ktc_encryptionKey mitkey; struct ktc_encryptionKey newkey; struct ktc_encryptionKey newmitkey; struct ktc_token token; struct passwd pwent; struct passwd *pw = &pwent; int insist; /* insist on good password quality */ int lexplicit = 0; /* servers specified explicitly */ int local; /* explicit cell is same a local cell */ int foundPassword = 0; /*Not yet, anyway */ int foundNewPassword = 0; /*Not yet, anyway */ int foundExplicitCell = 0; /*Not yet, anyway */ #ifdef DEFAULT_MITV4_STRINGTOKEY int dess2k = 1; #elif DEFAULT_AFS_STRINGTOKEY int dess2k = 0; #else int dess2k = -1; #endif /* blow away command line arguments */ for (i = 1; i < zero_argc; i++) memset(zero_argv[i], 0, strlen(zero_argv[i])); zero_argc = 0; /* first determine quiet flag based on -pipe switch */ Pipe = (as->parms[aPIPE].items ? 1 : 0); #if TIMEOUT signal(SIGALRM, timedout); alarm(30); #endif code = ka_Init(0); if (code || !(lcell = ka_LocalCell())) { #ifndef AFS_FREELANCE_CLIENT if (!Pipe) afs_com_err(rn, code, "Can't get local cell name!"); exit(1); #endif } code = rx_Init(0); if (code) { if (!Pipe) afs_com_err(rn, code, "Failed to initialize Rx"); exit(1); } strcpy(instance, ""); /* Parse our arguments. */ if (as->parms[aCELL].items) { /* * cell name explicitly mentioned; take it in if no other cell name * has already been specified and if the name actually appears. If * the given cell name differs from our own, we don't do a lookup. */ foundExplicitCell = 1; strncpy(realm, as->parms[aCELL].items->data, sizeof(realm)); } if (as->parms[aSERVERS].items) { /* explicit server list */ int i; struct cmd_item *ip; char *ap[MAXSERVERS + 2]; for (ip = as->parms[aSERVERS].items, i = 2; ip; ip = ip->next, i++) ap[i] = ip->data; ap[0] = ""; ap[1] = "-servers"; code = ubik_ParseClientList(i, ap, serverList); if (code) { if (!Pipe) afs_com_err(rn, code, "could not parse server list"); return code; } lexplicit = 1; } if (as->parms[aPRINCIPAL].items) { ka_ParseLoginName(as->parms[aPRINCIPAL].items->data, name, instance, cell); if (strlen(instance) > 0) if (!Pipe) fprintf(stderr, "Non-null instance (%s) may cause strange behavior.\n", instance); if (strlen(cell) > 0) { if (foundExplicitCell) { if (!Pipe) fprintf(stderr, "%s: May not specify an explicit cell twice.\n", rn); return -1; } foundExplicitCell = 1; strncpy(realm, cell, sizeof(realm)); } pw->pw_name = name; } else { /* No explicit name provided: use Unix uid. */ #ifdef AFS_NT40_ENV userNameLen = 128; if (GetUserName(userName, &userNameLen) == 0) { if (!Pipe) { fprintf(stderr, "Can't figure out your name in local cell %s from your user id.\n", lcell); fprintf(stderr, "Try providing the user name.\n"); } exit(1); } pw->pw_name = userName; #else pw = getpwuid(getuid()); if (pw == 0) { if (!Pipe) { fprintf(stderr, "Can't figure out your name in local cell %s from your user id.\n", lcell); fprintf(stderr, "Try providing the user name.\n"); } exit(1); } #endif } if (as->parms[aPASSWORD].items) { /* * Current argument is the desired password string. Remember it in * our local buffer, and zero out the argument string - anyone can * see it there with ps! */ foundPassword = 1; strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd)); memset(as->parms[aPASSWORD].items->data, 0, strlen(as->parms[aPASSWORD].items->data)); } if (as->parms[aNEWPASSWORD].items) { /* * Current argument is the new password string. Remember it in * our local buffer, and zero out the argument string - anyone can * see it there with ps! */ foundNewPassword = 1; strncpy(npasswd, as->parms[aNEWPASSWORD].items->data, sizeof(npasswd)); memset(as->parms[aNEWPASSWORD].items->data, 0, strlen(as->parms[aNEWPASSWORD].items->data)); } #ifdef AFS_FREELANCE_CLIENT if (!foundExplicitCell && !lcell) { if (!Pipe) afs_com_err(rn, code, "no cell name provided"); exit(1); } #else if (!foundExplicitCell) strcpy(realm, lcell); #endif /* freelance */ if ((code = ka_CellToRealm(realm, realm, &local))) { if (!Pipe) afs_com_err(rn, code, "Can't convert cell to realm"); exit(1); } lcstring(cell, realm, sizeof(cell)); ka_PrintUserID("Changing password for '", pw->pw_name, instance, "'"); printf(" in cell '%s'.\n", cell); /* Get the password if it wasn't provided. */ if (!foundPassword) { if (Pipe) getpipepass(passwd, sizeof(passwd)); else { code = read_pass(passwd, sizeof(passwd), "Old password: "******"reading password"); exit(1); } } } ka_StringToKey(passwd, realm, &key); des_string_to_key(passwd, ktc_to_cblockptr(&mitkey)); give_to_child(passwd); /* Get new password if it wasn't provided. */ insist = 0; if (!foundNewPassword) { if (Pipe) getpipepass(npasswd, sizeof(npasswd)); else { do { code = read_pass(npasswd, sizeof(npasswd), "New password (RETURN to abort): ", 0); if (code || (strlen(npasswd) == 0)) { if (code) code = KAREADPW; goto no_change; } } while (password_bad(npasswd)); code = read_pass(verify, sizeof(verify), "Retype new password: "******"Mismatch - "); goto no_change; } memset(verify, 0, sizeof(verify)); } } if ((code = password_bad(npasswd))) { /* assmt here! */ goto no_change_no_msg; } #if TRUNCATEPASSWORD if (strlen(npasswd) > 8) { npasswd[8] = 0; fprintf(stderr, "%s: password too long, only the first 8 chars will be used.\n", rn); } else npasswd[8] = 0; /* in case the password was exactly 8 chars long */ #endif ka_StringToKey(npasswd, realm, &newkey); des_string_to_key(npasswd, ktc_to_cblockptr(&newmitkey)); memset(npasswd, 0, sizeof(npasswd)); if (lexplicit) ka_ExplicitCell(realm, serverList); /* Get an connection to kaserver's admin service in desired cell. Set the * lifetime above the time uncertainty so that badly skewed clocks are * reported when the ticket is decrypted. Then give us 10 seconds to * actually get our work done if the clocks are skewed by only 14:59. * NOTE: Kerberos lifetime encoding will round this up to next 5 minute * interval, namely 20 minutes. */ #define ADMIN_LIFETIME (KTC_TIME_UNCERTAINTY+1) code = ka_GetAdminToken(pw->pw_name, instance, realm, &key, ADMIN_LIFETIME, &token, /*!new */ 0); if (code == KABADREQUEST) { code = ka_GetAdminToken(pw->pw_name, instance, realm, &mitkey, ADMIN_LIFETIME, &token, /*!new */ 0); if ((code == KABADREQUEST) && (strlen(passwd) > 8)) { /* try with only the first 8 characters incase they set their password * with an old style passwd program. */ char pass8[9]; strncpy(pass8, passwd, 8); pass8[8] = 0; ka_StringToKey(pass8, realm, &key); memset(pass8, 0, sizeof(pass8)); memset(passwd, 0, sizeof(passwd)); code = ka_GetAdminToken(pw->pw_name, instance, realm, &key, ADMIN_LIFETIME, &token, /*!new */ 0); #ifdef notdef /* the folks in testing really *hate* this message */ if (code == 0) { fprintf(stderr, "Warning: only the first 8 characters of your old password were significant.\n"); } #endif if (code == 0) { if (dess2k == -1) dess2k = 0; } } else { if (dess2k == -1) dess2k = 1; } } else { if (dess2k == -1) dess2k = 0; } memset(&mitkey, 0, sizeof(mitkey)); memset(&key, 0, sizeof(key)); if (code == KAUBIKCALL) afs_com_err(rn, code, "(Authentication Server unavailable, try later)"); else if (code) { if (code == KABADREQUEST) fprintf(stderr, "%s: Incorrect old password.\n", rn); else afs_com_err(rn, code, "so couldn't change password"); } else { code = ka_AuthServerConn(realm, KA_MAINTENANCE_SERVICE, &token, &conn); if (code) afs_com_err(rn, code, "contacting Admin Server"); else { if (dess2k == 1) code = ka_ChangePassword(pw->pw_name, instance, conn, 0, &newmitkey); else code = ka_ChangePassword(pw->pw_name, instance, conn, 0, &newkey); memset(&newkey, 0, sizeof(newkey)); memset(&newmitkey, 0, sizeof(newmitkey)); if (code) { char *reason; reason = (char *)afs_error_message(code); fprintf(stderr, "%s: Password was not changed because %s\n", rn, reason); } else printf("Password changed.\n\n"); } } memset(&newkey, 0, sizeof(newkey)); memset(&newmitkey, 0, sizeof(newmitkey)); /* Might need to close down the ubik_Client connection */ if (conn) { ubik_ClientDestroy(conn); conn = 0; } rx_Finalize(); terminate_child(); exit(code); no_change: /* yuck, yuck, yuck */ if (code) afs_com_err(rn, code, "getting new password"); no_change_no_msg: memset(&key, 0, sizeof(key)); memset(npasswd, 0, sizeof(npasswd)); printf("Password for '%s' in cell '%s' unchanged.\n\n", pw->pw_name, cell); terminate_child(); exit(code ? code : 1); }
static int Main(struct cmd_syndesc *as, void *arock) { int code; char name[MAXKTCNAMELEN]; char instance[MAXKTCNAMELEN]; char newCell[MAXKTCREALMLEN]; char *cell; long serverList[MAXSERVERS]; extern struct passwd *getpwuid(); struct passwd *pw; struct ktc_encryptionKey key; char passwd[BUFSIZ]; int cellSpecified; int i; int verbose = (as->parms[1].items != 0); int hostUsage = (as->parms[2].items != 0); int waitReap = (as->parms[4].items != 0); int doAuth = (as->parms[5].items != 0); int number; /* number of iterations */ int callsPerSecond; /* to allow conn GC to run */ unsigned long lo, hi; /* mem usage */ unsigned long highWater; /* mem usage after reap period */ unsigned long lastWater; /* mem usage after last msg */ int serversUse[MAXSERVERS]; /* usage of each server */ long serversHost[MAXSERVERS]; /* host addr */ unsigned long startTime; unsigned long now; lo = 0; whoami = as->a0name; newCell[0] = 0; if (as->parms[0].items) number = atoi(as->parms[0].items->data); else number = 100; if (as->parms[3].items) callsPerSecond = atoi(as->parms[3].items->data); else callsPerSecond = 1; if (doAuth && hostUsage) { fprintf(stderr, "Can't report host usage when calling UserAuthenticate\n"); return -1; } if (as->parms[12].items) { /* if username specified */ code = ka_ParseLoginName(as->parms[12].items->data, name, instance, newCell); if (code) { afs_com_err(whoami, code, "parsing user's name '%s'", as->parms[12].items->data); return code; } if (strlen(newCell) > 0) cellSpecified = 1; } else { /* No explicit name provided: use Unix uid. */ pw = getpwuid(getuid()); if (pw == 0) { printf("Can't figure out your name from your user id.\n"); return KABADCMD; } strncpy(name, pw->pw_name, sizeof(name)); strcpy(instance, ""); strcpy(newCell, ""); } if (strcmp(as->parms[14].name, "-cell") == 0) { if (as->parms[14].items) { /* if cell specified */ if (cellSpecified) printf("Duplicate cell specification not allowed\n"); else strncpy(newCell, as->parms[14].items->data, sizeof(newCell)); } } code = ka_ExpandCell(newCell, newCell, 0 /*local */ ); if (code) { afs_com_err(whoami, code, "Can't expand cell name"); return code; } cell = newCell; if (as->parms[13].items) { /* if password specified */ strncpy(passwd, as->parms[13].items->data, sizeof(passwd)); memset(as->parms[13].items->data, 0, strlen(as->parms[13].items->data)); } else { char msg[sizeof(name) + 15]; if (as->parms[12].items) strcpy(msg, "Admin Password: "******"Password for %s: ", name); code = read_pw_string(passwd, sizeof(passwd), msg, 0); if (code) code = KAREADPW; else if (strlen(passwd) == 0) code = KANULLPASSWORD; if (code) { afs_com_err(whoami, code, "reading password"); return code; } } if (as->parms[15].items) { struct cmd_item *ip; char *ap[MAXSERVERS + 2]; for (ip = as->parms[15].items, i = 2; ip; ip = ip->next, i++) ap[i] = ip->data; ap[0] = ""; ap[1] = "-servers"; code = ubik_ParseClientList(i, ap, serverList); if (code) { afs_com_err(whoami, code, "could not parse server list"); return code; } ka_ExplicitCell(cell, serverList); } if (!doAuth) { ka_StringToKey(passwd, cell, &key); memset(passwd, 0, sizeof(passwd)); } if (hostUsage) { memset(serversUse, 0, sizeof(serversUse)); memset(serversHost, 0, sizeof(serversHost)); } startTime = time(0); for (i = 0; i < number; i++) { if (doAuth) { char *reason; code = ka_UserAuthenticateLife(0, name, instance, cell, passwd, 0, &reason); if (code) { fprintf(stderr, "Unable to authenticate to AFS because %s.\n", reason); return code; } } else { struct ktc_token token; struct ktc_token *pToken; struct ubik_client *ubikConn; struct kaentryinfo tentry; int c; code = ka_GetAdminToken(name, instance, cell, &key, 3600, &token, 1 /*new */ ); if (code) { afs_com_err(whoami, code, "getting admin token"); return code; } pToken = &token; if (token.ticketLen == 0) { fprintf("Can't get admin token\n"); return -1; } code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, pToken, &ubikConn); if (code) { afs_com_err(whoami, code, "Getting AuthServer ubik conn"); return code; } if (verbose) for (c = 0; c < MAXSERVERS; c++) { struct rx_connection *rxConn = ubik_GetRPCConn(ubikConn, c); struct rx_peer *peer; if (rxConn == 0) break; peer = rx_PeerOf(rxConn); printf("conn to %s:%d secObj:%x\n", inet_ntoa(rx_HostOf(peer)), ntohs(rx_PortOf(peer)), rxConn->securityObject); } code = ubik_Call(KAM_GetEntry, ubikConn, 0, name, instance, KAMAJORVERSION, &tentry); if (code) { afs_com_err(whoami, code, "getting information for %s.%s", name, instance); return code; } for (c = 0; c < MAXSERVERS; c++) { struct rx_connection *rxConn = ubik_GetRPCConn(ubikConn, c); int d; if (rxConn == 0) break; if (rxConn->serial > 0) { long host = rx_HostOf(rx_PeerOf(rxConn)); for (d = 0; d < MAXSERVERS; d++) { if (serversHost[d] == 0) serversHost[d] = host; if (host == serversHost[d]) { serversUse[d]++; break; } } } if (verbose) printf("serial is %d\n", rxConn->serial); } ubik_ClientDestroy(ubikConn); } now = time(0); if (!lo) lo = sbrk(0); if (i && ((i & 0x3f) == 0)) { unsigned long this = sbrk(0); printf(" mem after %d: lo=%x, cur=%x => %d (@ %d)\n", i, lo, this, this - lo, (this - lo) / i); if (highWater && (lastWater != this)) { lastWater = this; printf(" core leaking (after %d) should be %x, is %x\n", i, highWater, this); } } if ((highWater == 0) && ((now - startTime) > 61)) { highWater = sbrk(0); lastWater = highWater; printf(" mem highWater mark (after %d) should be %x\n", i, highWater); } if (callsPerSecond) { long target; if (callsPerSecond > 0) target = i / callsPerSecond; else /* if negative interpret as seconds per call */ target = i * (-callsPerSecond); target = (startTime + target) - now; if (target > 0) IOMGR_Sleep(target); } }
afs_int32 InitThisModule(void) { /*InitThisModule */ #ifdef USS_KAUTH_DB static char rn[] = "uss_kauth:InitThisModule"; #endif afs_int32 code; char prompt[2 * MAXKTCNAMELEN + 20]; char *reasonString, longPassBuff[1024], shortPassBuff[9]; struct ktc_encryptionKey key; struct ktc_token token; struct ktc_principal Name, tok; /* * Only call this routine once. */ if (initDone) return (0); /* * Pull out the caller's administrator token if they have one. */ code = ka_GetAdminToken(0, 0, uss_Cell, 0, 10 * 60 * 60, &token, 0 /*new */ ); if (code) { if (Pipe) { strncpy(longPassBuff, getpipepass(), sizeof(longPassBuff)); } else { /* * Nope, no admin tokens available. Get the key based on the * full password and try again. */ sprintf(prompt, "Password for '%s", uss_AccountCreator); if (CreatorInstance[0]) sprintf(prompt + strlen(prompt), ".%s", CreatorInstance); strcat(prompt, "': "); code = ka_UserReadPassword(prompt, /*Prompt to use */ longPassBuff, /*Long pwd buffer */ sizeof(longPassBuff), /*Size of above */ &reasonString); if (code) { afs_com_err(uss_whoami, code, "while getting password "); #ifdef USS_KAUTH_DB printf("%s: Error code from ka_UserReadPassword(): %d\n", rn, code); #endif /* USS_KAUTH_DB */ return (code); } } ka_StringToKey(longPassBuff, uss_Cell, &key); code = ka_GetAdminToken(uss_AccountCreator, CreatorInstance, uss_Cell, &key, 24 * 60 * 60, &token, 0 /*new */ ); if (code) { if ((code == KABADREQUEST) && (strlen(longPassBuff) > 8)) { /* * The key we provided just doesn't work, yet we * suspect that since the password is greater than 8 * chars, it might be the case that we really need * to truncate the password to generate the appropriate * key. */ afs_com_err(uss_whoami, code, "while getting administrator token (trying shortened password next...)"); #ifdef USS_KAUTH_DB printf("%s: Error code from ka_GetAdminToken: %d\n", rn, code); #endif /* USS_KAUTH_DB */ strncpy(shortPassBuff, longPassBuff, 8); shortPassBuff[8] = 0; ka_StringToKey(shortPassBuff, uss_Cell, &key); code = ka_GetAdminToken(uss_AccountCreator, CreatorInstance, uss_Cell, &key, 24 * 60 * 60, &token, 0 /*new */ ); if (code) { afs_com_err(uss_whoami, code, "while getting administrator token (possibly wrong password, or not an administrative account)"); #ifdef USS_KAUTH_DB printf("%s: Error code from ka_GetAdminToken: %d\n", rn, code); #endif /* USS_KAUTH_DB */ return (code); } else { /* * The silly administrator has a long password! Tell * him or her off in a polite way. */ printf ("%s: Shortened password accepted by the Authentication Server\n", uss_whoami); } } /*Try a shorter password */ else { /* * We failed to get an admin token, but the password is * of a reasonable length, so we're just hosed. */ afs_com_err(uss_whoami, code, "while getting administrator token (possibly wrong password, or not an administrative account)"); #ifdef USS_KAUTH_DB printf("%s: Error code from ka_GetAdminToken: %d\n", rn, code); #endif /* USS_KAUTH_DB */ return (code); } /*Even the shorter password didn't work */ } /*Key from given password didn't work */ } /*First attempt to get admin token failed */ /* * At this point, we have acquired an administrator token. Let's * proceed to set up a connection to the AuthServer. */ #ifdef USS_KAUTH_DB_INSTANCE fprintf(stderr, "%s: CreatorInstance after ka_GetAdminToken(): '%s', %d bytes\n", rn, CreatorInstance, strlen(CreatorInstance)); #endif /* USS_KAUTH_DB_INSTANCE */ /* * Set up the connection to the AuthServer read/write site. */ code = ka_AuthServerConn(uss_Cell, KA_MAINTENANCE_SERVICE, &token, &uconn_kauthP); if (code) { afs_com_err(uss_whoami, code, "while establishing Authentication Server connection"); #ifdef USS_KAUTH_DB printf("%s: Error code from ka_AuthServerConn: %d\n", rn, code); #endif /* USS_KAUTH_DB */ return (code); } if (uss_Administrator[0]) { /* * We must check to see if we have local tokens for admin since he'll may do * various pioctl or calls to protection server that require tokens. Remember * to remove this tokens at the end of the program... */ strcpy(Name.name, "afs"); Name.instance[0] = '\0'; strncpy(Name.cell, uss_Cell, sizeof(Name.cell)); if ((code = ktc_GetToken(&Name, &token, sizeof(struct ktc_token), &tok))) { code = ka_UserAuthenticateLife(0, uss_AccountCreator, CreatorInstance, uss_Cell, longPassBuff, 10 * 60 * 60, &reasonString); if (!code) doUnlog = 1; } } /* * Declare our success. */ initDone = 1; return (0); } /*InitThisModule */