afs_int32 uss_kauth_DelUser(char *a_user) { /*uss_kauth_DelUser */ #ifdef USS_KAUTH_DB static char rn[] = "uss_kauth_DelUser"; /*Routine name */ #endif afs_int32 code; /*Return code */ if (uss_SkipKaserver) { /* * Don't talk to the kaserver; assume calls succeded and simply return. * Amasingly people want to update it (most likely kerberos) themselves... */ if (uss_verbose) printf ("[Skip Kaserver option - Deleting of user %s in Authentication DB not done]\n", a_user); return 0; } /* * Make sure the module has been initialized before we start trying * to talk to AuthServers. */ if (!initDone) { code = InitThisModule(); if (code) exit(code); } if (!uss_DryRun) { #ifdef USS_KAUTH_DB_INSTANCE printf("%s: KAM_DeleteUser: user='******', CreatorInstance='%s'\n", uss_whoami, a_user, CreatorInstance); #endif /* USS_KAUTH_DB_INSTANCE */ if (uss_verbose) printf("Deleting user '%s' from Authentication DB\n", a_user); code = ubik_KAM_DeleteUser( uconn_kauthP, /*Ubik client connection struct */ 0, /*Flags */ a_user, /*User name to delete */ UserInstance); /*set in CheckUserName() */ if (code) { if (code == KANOENT) { if (uss_verbose) printf ("%s: No entry for user '%s' in Authentication DB\n", uss_whoami, a_user); return (0); } else { afs_com_err(uss_whoami, code, "while deleting entry in Authentication DB\n"); #ifdef USS_KAUTH_DB printf("%s: Error code from KAM_DeleteUser: %d\n", rn, code); #endif /* USS_KAUTH_DB */ return (code); } } /*KAM_DeleteUser failed */ } /*Not a dry run */ else printf("\t[Dry run - user '%s' NOT deleted from Authentication DB]\n", a_user); return (0); } /*uss_kauth_DelUser */
/* * Requires that you already possess a TGT. */ afs_int32 ka_GetAFSTicket(char *name, char *instance, char *realm, Date lifetime, afs_int32 flags) { afs_int32 code; struct ktc_token token; struct ktc_principal server, client; code = ka_GetServerToken("afs", "", realm, lifetime, &token, /*new */ 1, /*dosetpag */ flags); if (code) return code; if (ktc_OldPioctl()) { int local; char username[MAXKTCNAMELEN]; afs_int32 viceId; int len; char *whoami = "UserAuthenticate: ptserver"; strcpy(server.name, "afs"); strcpy(server.instance, ""); code = ka_ExpandCell(realm, server.cell, &local); if (code) return code; code = pr_Initialize(0, AFSDIR_CLIENT_ETC_DIRPATH, server.cell); if (code) { afs_com_err(whoami, code, "initializing ptserver in cell '%s'", server.cell); return 0; } len = strlen(name); if (instance[0]) len += strlen(instance) + 1; if (len >= sizeof(username)) { fprintf(stderr, "user's name '%s'.'%s' would be too large\n", name, instance); return 0; } strcpy(username, name); if (instance[0]) { strcat(username, "."); strcat(username, instance); } code = pr_SNameToId(username, &viceId); /* Before going further, shutdown the pr ubik connection */ pr_End(); if ((code == 0) && (viceId == ANONYMOUSID)) code = PRNOENT; if (code) { afs_com_err(whoami, code, "translating %s to id", username); return 0; } sprintf(client.name, "AFS ID %d", viceId); strcpy(client.instance, ""); strcpy(client.cell, server.cell); code = ktc_SetToken(&server, &token, &client, /*dosetpag */ 0); if (code) return code; } return code; }
static int CommandProc(struct cmd_syndesc *as, void *arock) { krb5_principal princ = 0; char *cell, *pname, **hrealms, *service; char service_temp[MAXKTCREALMLEN + 20]; krb5_creds incred[1], mcred[1], *outcred = 0, *afscred; krb5_ccache cc = 0; #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC krb5_get_init_creds_opt *gic_opts; #else krb5_get_init_creds_opt gic_opts[1]; #endif char *tofree = NULL, *outname; int code; char *what; int i, dosetpag, evil, noprdb, id; #ifdef AFS_RXK5 int authtype; #endif krb5_data enc_part[1]; time_t lifetime; /* requested ticket lifetime */ krb5_prompter_fct pf = NULL; char *pass = 0; void *pa = 0; struct kp_arg klog_arg[1]; char passwd[BUFSIZ]; struct afsconf_cell cellconfig[1]; static char rn[] = "klog"; /*Routine name */ static int Pipe = 0; /* reading from a pipe */ static int Silent = 0; /* Don't want error messages */ int writeTicketFile = 0; /* write ticket file to /tmp */ service = 0; memset(incred, 0, sizeof *incred); /* blow away command line arguments */ for (i = 1; i < zero_argc; i++) memset(zero_argv[i], 0, strlen(zero_argv[i])); zero_argc = 0; memset(klog_arg, 0, sizeof *klog_arg); /* first determine quiet flag based on -silent switch */ Silent = (as->parms[aSILENT].items ? 1 : 0); if (Silent) { afs_set_com_err_hook(silent_errors); } if ((code = krb5_init_context(&k5context))) { afs_com_err(rn, code, "while initializing Kerberos 5 library"); KLOGEXIT(code); } if ((code = rx_Init(0))) { afs_com_err(rn, code, "while initializing rx"); KLOGEXIT(code); } initialize_U_error_table(); /*initialize_krb5_error_table();*/ initialize_RXK_error_table(); initialize_KTC_error_table(); initialize_ACFG_error_table(); /* initialize_rx_error_table(); */ if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) { afs_com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))", AFSDIR_CLIENT_ETC_DIRPATH); KLOGEXIT(1); } /* * Enable DES enctypes, which are currently still required for AFS. * krb5_allow_weak_crypto is MIT Kerberos 1.8. krb5_enctype_enable is * Heimdal. */ #if defined(HAVE_KRB5_ENCTYPE_ENABLE) i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC); if (i) krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC); #elif defined(HAVE_KRB5_ALLOW_WEAK_CRYPTO) krb5_allow_weak_crypto(k5context, 1); #endif /* Parse remaining arguments. */ dosetpag = !! as->parms[aSETPAG].items; Pipe = !! as->parms[aPIPE].items; writeTicketFile = !! as->parms[aTMP].items; noprdb = !! as->parms[aNOPRDB].items; evil = (always_evil&1) || !! as->parms[aUNWRAP].items; #ifdef AFS_RXK5 authtype = 0; if (as->parms[aK5].items) authtype |= FORCE_RXK5; if (as->parms[aK4].items) authtype |= FORCE_RXKAD; if (!authtype) authtype |= env_afs_rxk5_default(); #endif cell = as->parms[aCELL].items ? as->parms[aCELL].items->data : 0; if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) { if (cell) afs_com_err(rn, code, "Can't get cell information for '%s'", cell); else afs_com_err(rn, code, "Can't get determine local cell!"); KLOGEXIT(code); } if (as->parms[aKRBREALM].items) { code = krb5_set_default_realm(k5context, as->parms[aKRBREALM].items->data); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", as->parms[aKRBREALM].items->data); KLOGEXIT(code); } } else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) { afs_com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n", cellconfig->hostName[0], cellconfig->name); KLOGEXIT(code); } else { if (hrealms && *hrealms) { code = krb5_set_default_realm(k5context, *hrealms); if (code) { afs_com_err(rn, code, "Can't make <%s> the default realm", *hrealms); KLOGEXIT(code); } } if (hrealms) krb5_free_host_realm(k5context, hrealms); } id = getuid(); if (as->parms[aPRINCIPAL].items) { pname = as->parms[aPRINCIPAL].items->data; } else { /* No explicit name provided: use Unix uid. */ struct passwd *pw; pw = getpwuid(id); if (pw == 0) { afs_com_err(rn, 0, "Can't figure out your name from your user id (%d).", id); if (!Silent) fprintf(stderr, "%s: Try providing the user name.\n", rn); KLOGEXIT(1); } pname = pw->pw_name; } code = krb5_parse_name(k5context, pname, &princ); if (code) { afs_com_err(rn, code, "Can't parse principal <%s>", pname); KLOGEXIT(code); } 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! */ strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd)); memset(as->parms[aPASSWORD].items->data, 0, strlen(as->parms[aPASSWORD].items->data)); pass = passwd; } if (as->parms[aLIFETIME].items) { char *life = as->parms[aLIFETIME].items->data; char *sp; /* string ptr to rest of life */ lifetime = 3600 * strtol(life, &sp, 0); /* hours */ if (sp == life) { bad_lifetime: if (!Silent) fprintf(stderr, "%s: translating '%s' to lifetime failed\n", rn, life); return 1; } if (*sp == ':') { life = sp + 1; /* skip the colon */ lifetime += 60 * strtol(life, &sp, 0); /* minutes */ if (sp == life) goto bad_lifetime; if (*sp == ':') { life = sp + 1; lifetime += strtol(life, &sp, 0); /* seconds */ if (sp == life) goto bad_lifetime; if (*sp) goto bad_lifetime; } else if (*sp) goto bad_lifetime; } else if (*sp) goto bad_lifetime; } else lifetime = 0; /* Get the password if it wasn't provided. */ if (!pass) { if (Pipe) { strncpy(passwd, getpipepass(), sizeof(passwd)); pass = passwd; } else { pf = klog_prompter; pa = klog_arg; } } service = 0; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { tofree = get_afs_krb5_svc_princ(cellconfig); snprintf(service_temp, sizeof service_temp, "%s", tofree); } else #endif snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name); klog_arg->pp = &pass; klog_arg->pstore = passwd; klog_arg->allocated = sizeof(passwd); /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/ #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC code = krb5_get_init_creds_opt_alloc(k5context, &gic_opts); if (code) { afs_com_err(rn, code, "Can't allocate get_init_creds options"); KLOGEXIT(code); } #else krb5_get_init_creds_opt_init(gic_opts); #endif for (;;) { code = krb5_get_init_creds_password(k5context, incred, princ, pass, pf, /* prompter */ pa, /* data */ 0, /* start_time */ 0, /* in_tkt_service */ gic_opts); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) break; } memset(passwd, 0, sizeof(passwd)); if (code) { char *r = 0; if (krb5_get_default_realm(k5context, &r)) r = 0; if (r) afs_com_err(rn, code, "Unable to authenticate in realm %s", r); else afs_com_err(rn, code, "Unable to authenticate to use cell %s", cellconfig->name); if (r) free(r); KLOGEXIT(code); } for (;;writeTicketFile = 0) { if (writeTicketFile) { what = "getting default ccache"; code = krb5_cc_default(k5context, &cc); } else { what = "krb5_cc_resolve"; code = krb5_cc_resolve(k5context, "MEMORY:core", &cc); if (code) goto Failed; } what = "initializing ccache"; code = krb5_cc_initialize(k5context, cc, princ); if (code) goto Failed; what = "writing Kerberos ticket file"; code = krb5_cc_store_cred(k5context, cc, incred); if (code) goto Failed; if (writeTicketFile) fprintf(stderr, "Wrote ticket file to %s\n", krb5_cc_get_name(k5context, cc)); break; Failed: if (code) afs_com_err(rn, code, "%s", what); if (writeTicketFile) { if (cc) { krb5_cc_close(k5context, cc); cc = 0; } continue; } KLOGEXIT(code); } for (service = service_temp;;service = "afs") { memset(mcred, 0, sizeof *mcred); mcred->client = princ; code = krb5_parse_name(k5context, service, &mcred->server); if (code) { afs_com_err(rn, code, "Unable to parse service <%s>\n", service); KLOGEXIT(code); } if (tofree) { free(tofree); tofree = 0; } if (!(code = krb5_unparse_name(k5context, mcred->server, &outname))) tofree = outname; else outname = service; code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred); krb5_free_principal(k5context, mcred->server); if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break; #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) break; #endif } afscred = outcred; if (code) { afs_com_err(rn, code, "Unable to get credentials to use %s", outname); KLOGEXIT(code); } #ifdef AFS_RXK5 if (authtype & FORCE_RXK5) { struct ktc_principal aserver[1]; int viceid = 555; memset(aserver, 0, sizeof *aserver); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } else #endif { struct ktc_principal aserver[1], aclient[1]; struct ktc_token atoken[1]; memset(atoken, 0, sizeof *atoken); if (evil) { size_t elen = enc_part->length; atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY; if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data, afscred->ticket.length, (char **) &enc_part->data, &elen)) { afs_com_err(rn, 0, "Can't unwrap %s AFS credential", cellconfig->name); KLOGEXIT(1); } } else { atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5; *enc_part = afscred->ticket; } atoken->startTime = afscred->times.starttime; atoken->endTime = afscred->times.endtime; if (tkt_DeriveDesKey(get_creds_enctype(afscred), get_cred_keydata(afscred), get_cred_keylen(afscred), &atoken->sessionKey)) { afs_com_err(rn, 0, "Cannot derive DES key from enctype %i of length %u", get_creds_enctype(afscred), (unsigned)get_cred_keylen(afscred)); KLOGEXIT(1); } memcpy(atoken->ticket, enc_part->data, atoken->ticketLen = enc_part->length); memset(aserver, 0, sizeof *aserver); strncpy(aserver->name, "afs", 4); strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1); memset(aclient, 0, sizeof *aclient); i = realm_len(k5context, afscred->client); if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1; memcpy(aclient->cell, realm_data(k5context, afscred->client), i); if (!noprdb) { int viceid = 0; k5_to_k4_name(k5context, afscred->client, aclient); code = whoami(atoken, cellconfig, aclient, &viceid); if (code) { afs_com_err(rn, code, "Can't get your viceid for cell %s", cellconfig->name); *aclient->name = 0; } else snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid); } if (!*aclient->name) k5_to_k4_name(k5context, afscred->client, aclient); code = ktc_SetToken(aserver, atoken, aclient, dosetpag); if (code) { afs_com_err(rn, code, "Unable to store tokens for cell %s\n", cellconfig->name); KLOGEXIT(1); } } krb5_free_principal(k5context, princ); krb5_free_cred_contents(k5context, incred); if (outcred) krb5_free_creds(k5context, outcred); if (cc) krb5_cc_close(k5context, cc); if (tofree) free(tofree); return 0; }
int bc_SetExpCmd(struct cmd_syndesc *as, void *arock) { char *dname; /* dump schedule name */ struct cmd_item *ti; struct bc_dumpSchedule *node, *parent; afs_int32 expType, expDate; udbClientTextP ctPtr; int code; /* if an expiration date has been specified */ if (as->parms[1].items) { code = bc_ParseExpiration(&as->parms[1], &expType, &expDate); if (code) { printf("Invalid expiration date syntax\n"); return (1); } } else { /* no expiration date specified */ expDate = 0; expType = BC_NO_EXPDATE; } /* lock schedules and check validity */ ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE]; code = bc_LockText(ctPtr); if (code) ERROR(code); code = bc_UpdateDumpSchedule(); if (code) { afs_com_err(whoami, code, "; Can't retrieve dump schedule"); return (code); } /* process each dump name using the expiration date computed above */ for (ti = as->parms[0].items; ti != 0; ti = ti->next) { /* get next dump name to process */ dname = ti->data; /* validate the name dump name length */ if (strlen(dname) >= BU_MAX_DUMP_PATH) { code = -1; afs_com_err(whoami, 0, "Dump names must be < %d characters", BU_MAX_DUMP_PATH); afs_com_err(whoami, 0, "Dump %s not added", dname); continue; } code = FindDump(bc_globalConfig, dname, &parent, &node); if (code) { afs_com_err(whoami, 0, "Dump level %s not found", dname); continue; } node->expDate = expDate; node->expType = expType; } code = bc_SaveDumpSchedule(); if (code) { afs_com_err(whoami, code, "Cannot save dump schedule"); afs_com_err(whoami, 0, "Expiration changes effective for this session only"); } error_exit: if (ctPtr->lockHandle) bc_UnlockText(ctPtr); return (code); }
int bc_AddDumpCmd(struct cmd_syndesc *as, void *arock) { char *dname; /* dump schedule name */ int code; afs_int32 expType, expDate; struct cmd_item *ti; udbClientTextP ctPtr; /* if an expiration date has been specified */ if (as->parms[1].items) { code = bc_ParseExpiration(&as->parms[1], &expType, &expDate); if (code) { printf("Invalid expiration date syntax\n"); return (1); } } else { /* no expiration date specified */ expDate = 0; expType = BC_NO_EXPDATE; } /* lock schedules and check validity */ ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE]; code = bc_LockText(ctPtr); if (code) ERROR(code); code = bc_UpdateDumpSchedule(); if (code) { afs_com_err(whoami, code, "; Can't retrieve dump schedule"); return (code); } /* process each dump name using the expiration date computed above */ for (ti = as->parms[0].items; ti != 0; ti = ti->next) { /* get next dump name to process */ dname = ti->data; /* validate the name dump name length */ if (strlen(dname) >= BU_MAX_DUMP_PATH) { afs_com_err(whoami, 0, "Dump names must be < %d characters", BU_MAX_DUMP_PATH); afs_com_err(whoami, 0, "Dump %s not added", dname); code = -1; continue; } code = bc_CreateDumpSchedule(bc_globalConfig, dname, expDate, expType); if (code) { if (code == -1) afs_com_err(whoami, 0, "Dump already exists"); else if (code == -2) afs_com_err(whoami, 0, "Invalid path name '%s'", dname); else if (code == -3) afs_com_err(whoami, 0, "Name specification error"); else afs_com_err(whoami, code, "; Failed to create dump schedule"); continue; } /* save the new schedule item */ code = bc_SaveDumpSchedule(); if (code) { afs_com_err(whoami, code, "Cannot save dump schedule"); afs_com_err(whoami, 0, "Changes are temporary - for this session only"); break; } afs_com_err(whoami, 0, "Created new dump schedule %s", dname); } error_exit: if (ctPtr->lockHandle) bc_UnlockText(ctPtr); return (code); }
long rxkst_StartClient(struct clientParms *parms) { long code; long host; long scIndex; struct rx_securityClass *sc; whoami = parms->whoami; /* set this global variable */ host = GetServer(parms->server); if (parms->authentication >= 0) { long kvno = 0; char ticket[MAXKTCTICKETLEN]; int ticketLen; struct ktc_encryptionKey Ksession; if (parms->useTokens) code = GetToken(&kvno, &Ksession, &ticketLen, ticket, parms->cell); else code = GetTicket(&kvno, &Ksession, &ticketLen, ticket, parms->cell); if (code) return code; /* next, we have ticket, kvno and session key, authenticate the conn */ sc = (struct rx_securityClass *) rxkad_NewClientSecurityObject(parms->authentication, &Ksession, kvno, ticketLen, ticket); assert(sc); scIndex = RX_SECIDX_KAD; } else { /* unauthenticated connection */ sc = rxnull_NewClientSecurityObject(); assert(sc); scIndex = RX_SECIDX_NULL; } code = 0; if (!code && parms->callTest) { code = RunCallTest(parms, host, sc, scIndex); } if (!code && parms->hijackTest) { code = RunHijackTest(parms, host, sc, scIndex); } if (!code && (parms->printTiming || parms->fastCalls || parms->slowCalls || parms->copiousCalls)) { struct rx_connection *conn; conn = rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc, scIndex); if (conn) { code = RepeatLoadTest(parms, conn); rx_DestroyConnection(conn); } else code = RXKST_NEWCONNFAILED; } if (!code && parms->stopServer) { struct rx_connection *conn; conn = rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc, scIndex); if (conn) { code = RXKST_Kill(conn); if (code) { afs_com_err(whoami, code, "trying to stop server"); } rx_DestroyConnection(conn); } else code = RXKST_NEWCONNFAILED; } if (parms->printStats) { rx_PrintStats(stdout); #if 0 /* use rxdebug style iteration here */ rx_PrintPeerStats(stdout, rx_PeerOf(conn)); #endif } rxs_Release(sc); rx_Finalize(); if (code) { afs_com_err(parms->whoami, code, "test fails"); exit(13); } else { printf("Test Okay\n"); if (!parms->noExit) exit(0); } return 0; }
static long RunLoadTest(struct clientParms *parms, struct rx_connection *conn) { long code; struct client c; u_long fastCalls[MAX_CTHREADS]; u_long slowCalls[MAX_CTHREADS]; u_long copiousCalls[MAX_CTHREADS]; double start, interval; DivideUpCalls(parms->fastCalls, parms->threads, fastCalls); DivideUpCalls(parms->slowCalls, parms->threads, slowCalls); DivideUpCalls(parms->copiousCalls, parms->threads, copiousCalls); memset(&c, 0, sizeof(c)); c.conn = conn; c.sendLen = parms->sendLen; c.recvLen = parms->recvLen; c.fastCalls = fastCalls; c.slowCalls = slowCalls; c.copiousCalls = copiousCalls; start = ftime(); code = CallSimultaneously(parms->threads, &c, DoClient); if (code) { afs_com_err(whoami, code, "in DoClient"); return code; } interval = ftime() - start; if (parms->printTiming) { u_long totalCalls = parms->fastCalls + parms->slowCalls + parms->copiousCalls; int t = (interval / totalCalls) * 1000.0 + 0.5; if (totalCalls > 0) { printf("For %lu calls: %d msec/call\n", totalCalls, t); } if (parms->copiousCalls > 0) { long n = parms->sendLen + parms->recvLen; double kbps; int b; kbps = (double)(parms->copiousCalls * n) / (interval * 1000.0); b = kbps + 0.5; #if 0 I just cannot get printing of floats to work on the pmax ! !!!printf("%g %d %d %d\n", (float)kbps, b); printf("%g %d %d %d\n", kbps, b); fprintf(stdout, "%g %d %d\n", kbps, b); { char buf[100]; buf[sizeof(buf) - 1] = 0; sprintf(buf, "%g %d %d\n", kbps, b); assert(buf[sizeof(buf) - 1] == 0); printf("%s", buf); } #endif printf ("For %lu copious calls, %lu send + %lu recv = %lu bytes each: %d kbytes/sec\n", parms->copiousCalls, parms->sendLen, parms->recvLen, n, b); #if 0 printf("%g\n", kbps); #endif } } return 0; }
afs_int32 doDispatch(afs_int32 targc, char *targv[MAXV], afs_int32 dispatchCount) /* to prevent infinite recursion */ { char *sargv[MAXV]; afs_int32 sargc; afs_int32 code, c; FILE *fd; int i; int lineNumber; int noExecute; /* local capy of global variable */ char *internalLoadFile; lock_Dispatch(); loadFile = NULL; code = cmd_Dispatch(targc, targv); internalLoadFile = loadFile; unlock_Dispatch(); if (internalLoadFile) { /* Load a file in */ if (dispatchCount > MAXRECURSION) { /* Beware recursive loops. */ afs_com_err(whoami, 0, "Potential recursion: will not load file %s", internalLoadFile); code = -1; goto done; } fd = fopen(internalLoadFile, "r"); /* Open the load file */ if (!fd) { afs_com_err(whoami, errno, "; Cannot open file %s", internalLoadFile); code = -1; goto done; } noExecute = dontExecute; if (noExecute) printf("Would have executed the following commands:\n"); lineNumber = 0; while (fgets(lineBuffer, sizeof(lineBuffer) - 1, fd)) { /* Get commands from file */ lineNumber++; i = strlen(lineBuffer) - 1; if (lineBuffer[i] == '\n') /* Drop return at end of line */ lineBuffer[i] = '\0'; if (noExecute) printf(" %s\n", lineBuffer); /* echo */ else printf("------> %s\n", lineBuffer); /* echo */ if (!LineIsBlank(lineBuffer) && /* Skip if blank line */ (lineBuffer[0] != '#') && /* or comment */ (!noExecute)) { /* or no execute */ c = cmd_ParseLine(lineBuffer, sargv, &sargc, MAXV); if (c) { afs_com_err(whoami, c, "; Can't parse line"); } else { doDispatch(sargc, sargv, dispatchCount + 1); /* Recursive - ignore error */ cmd_FreeArgv(sargv); /* Free up arguments */ } } } fclose(fd); } done: if (internalLoadFile) free(internalLoadFile); return (code); }
int main(int argc, char **argv) { /*main */ char *targv[MAXV]; /*Ptr to parsed argv stuff */ afs_int32 targc; /*Num parsed arguments */ afs_int32 code; /*Return code */ struct cmd_syndesc *ts; /*Ptr to parsed command line */ int i; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); #endif Lock_Init(&dispatchLock); InitErrTabs(); /* init all the error tables which may be used */ /* setup the default backup dir */ DefaultConfDir = AFSDIR_SERVER_BACKUP_DIRPATH; /* Get early warning if the command is interacive mode or not */ interact = (((argc < 2) || (argv[1][0] == '-')) ? 1 : 0); cmd_SetBeforeProc(MyBeforeProc, NULL); ts = cmd_CreateSyntax("dump", bc_DumpCmd, NULL, "start dump"); cmd_AddParm(ts, "-volumeset", CMD_SINGLE, CMD_OPTIONAL, "volume set name"); cmd_AddParm(ts, "-dump", CMD_SINGLE, CMD_OPTIONAL, "dump level name"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-at", CMD_LIST, CMD_OPTIONAL, "Date/time to start dump"); cmd_AddParm(ts, "-append", CMD_FLAG, CMD_OPTIONAL, "append to existing dump set"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 5, "-n"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "load file"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("volrestore", bc_VolRestoreCmd, NULL, "restore volume"); cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "destination machine"); cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_REQUIRED, "destination partition"); cmd_AddParm(ts, "-volume", CMD_LIST, CMD_REQUIRED, "volume(s) to restore"); cmd_AddParm(ts, "-extension", CMD_SINGLE, CMD_OPTIONAL, "new volume name extension"); cmd_AddParm(ts, "-date", CMD_LIST, CMD_OPTIONAL, "date from which to restore"); cmd_AddParm(ts, "-portoffset", CMD_LIST, CMD_OPTIONAL, "TC port offsets"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 6, "-n"); cmd_AddParm(ts, "-usedump", CMD_SINGLE, CMD_OPTIONAL, "specify the dumpID to restore from"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("diskrestore", bc_DiskRestoreCmd, NULL, "restore partition"); cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine to restore"); cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_REQUIRED, "partition to restore"); cmd_AddParm(ts, "-portoffset", CMD_LIST, CMD_OPTIONAL, "TC port offset"); cmd_Seek(ts, 8); cmd_AddParm(ts, "-newserver", CMD_SINGLE, CMD_OPTIONAL, "destination machine"); cmd_AddParm(ts, "-newpartition", CMD_SINGLE, CMD_OPTIONAL, "destination partition"); cmd_AddParm(ts, "-extension", CMD_SINGLE, CMD_OPTIONAL, "new volume name extension"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 11, "-n"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("quit", bc_QuitCmd, NULL, "leave the program"); ts = cmd_CreateSyntax("volsetrestore", bc_VolsetRestoreCmd, NULL, "restore a set of volumes"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "volume set name"); cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "file name"); cmd_AddParm(ts, "-portoffset", CMD_LIST, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-extension", CMD_SINGLE, CMD_OPTIONAL, "new volume name extension"); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list what would be done, don't do it"); cmd_AddParmAlias(ts, 4, "-n"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("addhost", bc_AddHostCmd, NULL, "add host to config"); cmd_AddParm(ts, "-tapehost", CMD_SINGLE, CMD_REQUIRED, "tape machine name"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("delhost", bc_DeleteHostCmd, NULL, "delete host to config"); cmd_AddParm(ts, "-tapehost", CMD_SINGLE, CMD_REQUIRED, "tape machine name"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("listhosts", bc_ListHostsCmd, NULL, "list config hosts"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("jobs", bc_JobsCmd, NULL, "list running jobs"); ts = cmd_CreateSyntax("kill", bc_KillCmd, NULL, "kill running job"); cmd_AddParm(ts, "-id", CMD_SINGLE, CMD_REQUIRED, "job ID or dump set name"); ts = cmd_CreateSyntax("listvolsets", bc_ListVolSetCmd, NULL, "list volume sets"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "volume set name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("listdumps", bc_ListDumpScheduleCmd, NULL, "list dump schedules"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("addvolset", bc_AddVolSetCmd, NULL, "create a new volume set"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_REQUIRED, "volume set name"); cmd_AddParm(ts, "-temporary", CMD_FLAG, CMD_OPTIONAL, "temporary volume set"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("status", bc_GetTapeStatusCmd, NULL, "get tape coordinator status"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("delvolset", bc_DeleteVolSetCmd, NULL, "delete a volume set"); cmd_AddParm(ts, "-name", CMD_LIST, CMD_REQUIRED, "volume set name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("addvolentry", bc_AddVolEntryCmd, NULL, "add a new volume entry"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_REQUIRED, "volume set name"); cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "machine name"); cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_REQUIRED, "partition name"); cmd_AddParm(ts, "-volumes", CMD_SINGLE, CMD_REQUIRED, "volume name (regular expression)"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("delvolentry", bc_DeleteVolEntryCmd, NULL, "delete a volume set sub-entry"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_REQUIRED, "volume set name"); cmd_AddParm(ts, "-entry", CMD_SINGLE, CMD_REQUIRED, "volume set index"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("adddump", bc_AddDumpCmd, NULL, "add dump schedule"); cmd_AddParm(ts, "-dump", CMD_LIST, CMD_REQUIRED, "dump level name"); cmd_AddParm(ts, "-expires", CMD_LIST, CMD_OPTIONAL, "expiration date"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("deldump", bc_DeleteDumpCmd, NULL, "delete dump schedule"); cmd_AddParm(ts, "-dump", CMD_SINGLE, CMD_REQUIRED, "dump level name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("labeltape", bc_LabelTapeCmd, NULL, "label a tape"); cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "AFS tape name, defaults to NULL"); cmd_AddParm(ts, "-size", CMD_SINGLE, CMD_OPTIONAL, "tape size in Kbytes, defaults to size in tapeconfig"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-pname", CMD_SINGLE, CMD_OPTIONAL, "permanent tape name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("readlabel", bc_ReadLabelCmd, NULL, "read the label on tape"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("scantape", bc_ScanDumpsCmd, NULL, "dump information recovery from tape"); cmd_AddParm(ts, "-dbadd", CMD_FLAG, CMD_OPTIONAL, "add information to the database"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("volinfo", bc_dblookupCmd, NULL, "query the backup database"); cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_REQUIRED, "volume name"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("setexp", bc_SetExpCmd, NULL, "set/clear dump expiration dates"); cmd_AddParm(ts, "-dump", CMD_LIST, CMD_REQUIRED, "dump level name"); cmd_AddParm(ts, "-expires", CMD_LIST, CMD_OPTIONAL, "expiration date"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("savedb", bc_saveDbCmd, NULL, "save backup database"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-archive", CMD_LIST, CMD_OPTIONAL, "date time"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("restoredb", bc_restoreDbCmd, NULL, "restore backup database"); cmd_AddParm(ts, "-portoffset", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("dumpinfo", bc_dumpInfoCmd, NULL, "provide information about a dump in the database"); cmd_AddParm(ts, "-ndumps", CMD_SINGLE, CMD_OPTIONAL, "no. of dumps"); cmd_AddParm(ts, "-id", CMD_SINGLE, CMD_OPTIONAL, "dump id"); cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "detailed description"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("dbverify", bc_dbVerifyCmd, NULL, "check ubik database integrity"); cmd_AddParm(ts, "-detail", CMD_FLAG, CMD_OPTIONAL, "additional details"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("deletedump", bc_deleteDumpCmd, NULL, "delete dumps from the database"); cmd_AddParm(ts, "-dumpid", CMD_LIST, CMD_OPTIONAL, "dump id"); cmd_AddParm(ts, "-from", CMD_LIST, CMD_OPTIONAL, "date time"); cmd_AddParm(ts, "-to", CMD_LIST, CMD_OPTIONAL, "date time"); cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "TC port offset"); cmd_AddParm(ts, "-groupid", CMD_SINGLE, CMD_OPTIONAL, "group ID"); cmd_AddParm(ts, "-dbonly", CMD_FLAG, CMD_OPTIONAL, "delete the dump from the backup database only"); cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "always delete from backup database"); cmd_AddParm(ts, "-noexecute", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, ""); cmd_AddParm(ts, "-dryrun", CMD_FLAG, CMD_OPTIONAL, "list the dumps, don't delete anything"); cmd_AddParmAlias(ts, 8, "-n"); if (!interact) add_std_args(ts); ts = cmd_CreateSyntax("interactive", bc_interactCmd, NULL, "enter interactive mode"); add_std_args(ts); /* * Now execute the command. */ targc = 0; targv[targc++] = argv[0]; if (interact) targv[targc++] = "interactive"; for (i = 1; i < argc; i++) targv[targc++] = argv[i]; code = doDispatch(targc, targv, 1); if (!interact || !bcInit) { /* Non-interactive mode */ if (code) exit(-1); if (bcInit) code = bc_WaitForNoJobs(); /* wait for any jobs to finish */ exit(code); /* and exit */ } /* Iterate on command lines, interpreting user commands (interactive mode) */ while (1) { int ret; printf("backup> "); fflush(stdout); while ((ret = LWP_GetLine(lineBuffer, sizeof(lineBuffer))) == 0) printf("%s: Command line too long\n", whoami); /* line too long */ if (ret == -1) return 0; /* Got EOF */ if (!LineIsBlank(lineBuffer)) { code = cmd_ParseLine(lineBuffer, targv, &targc, MAXV); if (code) afs_com_err(whoami, code, "; Can't parse line: '%s'", afs_error_message(code)); else { doDispatch(targc, targv, 1); cmd_FreeArgv(targv); } } } } /*main */
static struct afsconf_typedKey * keyFromKeytab(int kvno, afsconf_keyType type, int subtype, const char *keytab, const char *princ) { int retval; krb5_principal principal; krb5_keyblock *key; krb5_context context; struct rx_opaque buffer; struct afsconf_typedKey *typedKey; krb5_init_context(&context); retval = krb5_parse_name(context, princ, &principal); if (retval) { afs_com_err("asetkey", retval, "while parsing AFS principal"); exit(1); } if (type == afsconf_rxkad) { retval = krb5_kt_read_service_key(context, (char *)keytab, principal, kvno, ENCTYPE_DES_CBC_CRC, &key); if (retval == KRB5_KT_NOTFOUND) retval = krb5_kt_read_service_key(context, (char *)keytab, principal, kvno, ENCTYPE_DES_CBC_MD5, &key); if (retval == KRB5_KT_NOTFOUND) retval = krb5_kt_read_service_key(context, (char *)keytab, principal, kvno, ENCTYPE_DES_CBC_MD4, &key); } else if (type == afsconf_rxkad_krb5) { retval = krb5_kt_read_service_key(context, (char *)keytab, principal, kvno, subtype, &key); } else { retval=AFSCONF_BADKEY; } if (retval == KRB5_KT_NOTFOUND) { char * princname = NULL; krb5_unparse_name(context, principal, &princname); if (type == afsconf_rxkad) { afs_com_err("asetkey", retval, "for keytab entry with Principal %s, kvno %u, " "DES-CBC-CRC/MD5/MD4", princname ? princname : princ, kvno); } else { afs_com_err("asetkey", retval, "for keytab entry with Principal %s, kvno %u", princname ? princname : princ, kvno); } exit(1); } if (retval != 0) { afs_com_err("asetkey", retval, "while extracting AFS service key"); exit(1); } if (type == afsconf_rxkad && deref_key_length(key) != 8) { fprintf(stderr, "Key length should be 8, but is really %u!\n", (unsigned int)deref_key_length(key)); exit(1); } rx_opaque_populate(&buffer, deref_key_contents(key), deref_key_length(key)); typedKey = afsconf_typedKey_new(type, kvno, subtype, &buffer); rx_opaque_freeContents(&buffer); krb5_free_principal(context, principal); krb5_free_keyblock(context, key); return typedKey; }
static int backupInit(void) { afs_int32 code; static int initd = 0; /* ever called? */ PROCESS watcherPid; PROCESS pid; /* LWP process ID */ /* Initialization */ initialize_CMD_error_table(); /* don't run more than once */ if (initd) { afs_com_err(whoami, 0, "Backup already initialized."); return 0; } initd = 1; code = bc_InitConfig((char *)DefaultConfDir); if (code) { afs_com_err(whoami, code, "Can't initialize from config files in directory '%s'", DefaultConfDir); return (code); } /* * Set up Rx. */ code = LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid); if (code) { afs_com_err(whoami, code, "; Can't initialize LWP"); return (code); } code = rx_Init(htons(0)); if (code) { afs_com_err(whoami, code, "; Can't initialize Rx"); return (code); } rx_SetRxDeadTime(60); /* VLDB initialization */ code = vldbClientInit(0, localauth, tcell, &cstruct, &tokenExpires); if (code) return (code); /* Backup database initialization */ code = udbClientInit(0, localauth, tcell); if (code) return (code); /* setup status monitoring thread */ initStatus(); code = LWP_CreateProcess(statusWatcher, 20480, LWP_NORMAL_PRIORITY, (void *)2, "statusWatcher", &watcherPid); if (code) { afs_com_err(whoami, code, "; Can't create status monitor task"); return (code); } return (0); }
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); }
afs_int32 udbClientInit(int noAuthFlag, int localauth, char *cellName) { struct afsconf_cell info; struct afsconf_dir *acdir; const char *confdir; int i; afs_int32 secFlags; afs_int32 code = 0; secFlags = parseSecFlags(noAuthFlag, localauth, &confdir); secFlags |= AFSCONF_SECOPTS_FALLBACK_NULL; if (cellName && cellName[0] == '\0') cellName = NULL; acdir = afsconf_Open(confdir); if (!acdir) { afs_com_err(whoami, 0, "Can't open configuration directory '%s'", confdir); ERROR(BC_NOCELLCONFIG); } code = afsconf_GetCellInfo(acdir, cellName, 0, &info); if (code) { afs_com_err(whoami, code, "; Can't find cell %s's hosts in %s/%s", cellName, confdir, AFSDIR_CELLSERVDB_FILE); ERROR(BC_NOCELLCONFIG); } code = afsconf_PickClientSecObj(acdir, secFlags, &info, cellName, &udbHandle.uh_secobj, &udbHandle.uh_scIndex, NULL); if (code) { afs_com_err(whoami, code, "(configuring connection security)"); ERROR(BC_NOCELLCONFIG); } if (&udbHandle.uh_scIndex == RX_SECIDX_NULL && !noAuthFlag) afs_com_err(whoami, 0, "Can't get tokens - running unauthenticated"); if (info.numServers > MAXSERVERS) { afs_com_err(whoami, 0, "Warning: %d BDB servers exist for cell '%s', can only remember the first %d", info.numServers, cellName, MAXSERVERS); info.numServers = MAXSERVERS; } /* establish connections to the servers. Check for failed connections? */ for (i = 0; i < info.numServers; i++) { udbHandle.uh_serverConn[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, htons(AFSCONF_BUDBPORT), BUDB_SERVICE, udbHandle.uh_secobj, udbHandle.uh_scIndex); } udbHandle.uh_serverConn[i] = 0; code = ubik_ClientInit(udbHandle.uh_serverConn, &udbHandle.uh_client); if (code) { afs_com_err(whoami, code, "; Can't initialize ubik connection to backup database"); ERROR(code); } /* Try to quickly find a good site by setting deadtime low */ for (i = 0; i < info.numServers; i++) rx_SetConnDeadTime(udbHandle.uh_client->conns[i], 1); code = ubik_BUDB_GetInstanceId(udbHandle.uh_client, 0, &udbHandle.uh_instanceId); /* Reset dead time back up to default */ for (i = 0; i < info.numServers; i++) rx_SetConnDeadTime(udbHandle.uh_client->conns[i], 60); /* If did not find a site on first quick pass, try again */ if (code == -1) code = ubik_BUDB_GetInstanceId(udbHandle.uh_client, 0, &udbHandle.uh_instanceId); if (code) { afs_com_err(whoami, code, "; Can't access backup database"); ERROR(code); } error_exit: if (acdir) afsconf_Close(acdir); return (code); }
afs_int32 uss_kauth_SetFields(char *username, char *expirestring, char *reuse, char *failures, char *lockout) { #ifdef USS_KAUTH_DB static char rn[] = "uss_kauth_SetFields"; #endif afs_int32 code; char misc_auth_bytes[4]; int i; afs_int32 flags = 0; Date expiration = 0; afs_int32 lifetime = 0; afs_int32 maxAssociates = -1; afs_int32 was_spare = 0; char instance = '\0'; int pwexpiry; int nfailures, locktime, hrs, mins; if (strlen(username) > uss_UserLen) { fprintf(stderr, "%s: * User field in add cmd too long (max is %d chars; truncated value is '%s')\n", uss_whoami, uss_UserLen, uss_User); return (-1); } strcpy(uss_User, username); code = uss_kauth_CheckUserName(); if (code) return (code); /* no point in doing this any sooner than necessary */ for (i = 0; i < 4; misc_auth_bytes[i++] = 0); pwexpiry = atoi(expirestring); if (pwexpiry < 0 || pwexpiry > 254) { fprintf(stderr, "Password lifetime range must be [0..254] days.\n"); fprintf(stderr, "Zero represents an unlimited lifetime.\n"); fprintf(stderr, "Continuing with default lifetime == 0 for user %s.\n", username); pwexpiry = 0; } misc_auth_bytes[0] = pwexpiry + 1; if (!strcmp(reuse, "noreuse")) { misc_auth_bytes[1] = KA_NOREUSEPW; } else { misc_auth_bytes[1] = KA_REUSEPW; if (strcmp(reuse, "reuse")) fprintf(stderr, "must specify \"reuse\" or \"noreuse\": \"reuse\" assumed\n"); } nfailures = atoi(failures); if (nfailures < 0 || nfailures > 254) { fprintf(stderr, "Failure limit must be in [0..254].\n"); fprintf(stderr, "Zero represents unlimited login attempts.\n"); fprintf(stderr, "Continuing with limit == 254 for user %s.\n", username); misc_auth_bytes[2] = 255; } else misc_auth_bytes[2] = nfailures + 1; hrs = 0; if (strchr(lockout, ':')) sscanf(lockout, "%d:%d", &hrs, &mins); else sscanf(lockout, "%d", &mins); locktime = hrs*60 + mins; if (hrs < 0 || hrs > 36 || mins < 0) { fprintf(stderr,"Lockout times must be either minutes or hh:mm.\n"); fprintf(stderr,"Lockout times must be less than 36 hours.\n"); return KABADCMD; } else if (locktime > 36*60) { fprintf(stderr, "Lockout times must be either minutes or hh:mm.\n"); fprintf(stderr, "Lockout times must be less than 36 hours.\n"); fprintf(stderr, "Continuing with lock time == forever for user %s.\n", username); misc_auth_bytes[3] = 1; } else { locktime = (locktime * 60 + 511) >> 9; /* ceil(l*60/512) */ misc_auth_bytes[3] = locktime + 1; } if (uss_SkipKaserver) { if (uss_verbose) printf("[Skipping Kaserver as requested]\n"); return 0; } /* * Make sure the module has been initialized before we start trying * to talk to AuthServers. */ if (!initDone) { code = InitThisModule(); if (code) exit(code); } if (!uss_DryRun) { if (uss_verbose) fprintf(stderr, "Setting options for '%s' in database.\n", username); was_spare = pack_long(misc_auth_bytes); if (was_spare || flags || expiration || lifetime || (maxAssociates >= 0)) { if (!expiration) expiration = uss_Expires; code = ubik_KAM_SetFields(uconn_kauthP, 0, username, &instance, flags, expiration, lifetime, maxAssociates, was_spare, /* spare */ 0); } else fprintf(stderr, "Must specify one of the optional parameters. Continuing...\n"); if (code) { afs_com_err(uss_whoami, code, "calling KAM_SetFields for %s", username); return (code); } } /*Not a dry run */ else fprintf(stderr, "\t[Dry run - user '%s' NOT changed.]\n", username); return (0); } /*uss_kauth_SetFields */
int main(int argc, char **argv) { register afs_int32 code; char op[8]; char name[PR_MAXNAMELEN]; afs_int32 id, oid = ANONYMOUSID, gid; afs_int32 pos; unsigned int i; int n; struct prentry entry; prlist alist; idlist lid; namelist lnames; struct hostent *hostinfo; struct in_addr *hostaddr; afs_int32 *ptr; char *foo; afs_int32 over; char *cell; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); #endif whoami = argv[0]; initialize_PT_error_table(); strcpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH); cell = 0; n = 1; while (n < argc) { int arglen = strlen(argv[n]); char arg[256]; lcstring(arg, argv[n], sizeof(arg)); #define IsArg(a) (strncmp (arg,a, arglen) == 0) if (IsArg("-testconfdir")) strncpy(confdir, argv[++n], sizeof(confdir)); else if (IsArg("client")) strncpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confdir)); else if (IsArg("server")) strncpy(confdir, AFSDIR_SERVER_ETC_DIRPATH, sizeof(confdir)); else if (IsArg("0") || IsArg("1") || IsArg("2")) security = atoi(argv[n]); else if (IsArg("-ignoreexist")) ignoreExist++; else if (IsArg("-cell")) cell = argv[++n]; else { printf ("Usage is: 'prclient [-testconfdir <dir> | server | client] [0 | 1 | 2] [-ignoreExist] [-cell <cellname>]\n"); exit(1); } n++; } printf("Using CellServDB file in %s\n", confdir); if (security == 0) printf("Making unauthenticated connection to prserver\n"); code = pr_Initialize(security, confdir, cell); if (code) { afs_com_err(whoami, code, "Couldn't initialize protection library"); exit(1); } while (1) { char *s; printf("pr> "); s = fgets(line, sizeof(line), stdin); if (s == NULL) break; lineProgress = 0; code = GetString(op, sizeof(op)); if (code) { afs_com_err(whoami, PRBADARG, "error reading opcode in line '%s', got '%.*s'", line, sizeof(op), op); exit(1); } if (strlen(op) == 0) continue; /* no input */ if (!strcmp(op, "cr")) { if (GetString(name, sizeof(name)) || GetInt32(&id) || GetInt32(&oid)) code = PRBADARG; /* use ubik_Call to do the work, finding an up server and handling * the job of finding a sync site, if need be */ else code = ubik_PR_INewEntry(pruclient, 0, name, id, oid); if (CodeOk(code)) afs_com_err(whoami, code, "on %s %s %d %d", op, name, id, oid); } else if (!strcmp(op, "sf")) { afs_int32 mask, access, gq, uq; if (GetInt32(&id) || GetXInt32(&mask) || GetXInt32(&access) || GetInt32(&gq) || GetInt32(&uq)) code = PRBADARG; else code = ubik_PR_SetFieldsEntry(pruclient, 0, id, mask, access, gq, uq, 0, 0); if (CodeOk(code)) afs_com_err(whoami, code, "on %s %d %x %x %d %d", op, id, mask, access, gq, uq); } else if (!strcmp(op, "ce")) { char newname[PR_MAXNAMELEN]; afs_int32 newid; if (GetInt32(&id) || GetString(newname, sizeof(newname)) || GetInt32(&oid) || GetInt32(&newid)) code = PRBADARG; else code = ubik_PR_ChangeEntry(pruclient, 0, id, newname, oid, newid); if (CodeOk(code)) afs_com_err(whoami, code, "on %s %d %s %d %d", op, id, newname, oid, newid); } else if (!strcmp(op, "wh")) { /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_WhereIsIt(pruclient, 0, id, &pos); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); else printf("location %d\n", pos); } else if (!strcmp(op, "du")) { memset(&entry, 0, sizeof(entry)); /* scanf("%d",&pos); */ if (GetInt32(&pos)) code = PRBADARG; else code = ubik_PR_DumpEntry(pruclient, 0, pos, (struct prdebugentry *)&entry); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { PrintEntry(pos, &entry, /*indent */ 0); #if 0 printf("The contents of the entry for %d are:\n", entry.id); printf("flags %d next %d\n", entry.flags, entry.next); printf("Groups (or members) \n"); for (i = 0; i < PRSIZE; i++) printf("%d\n", entry.entries[i]); printf("nextID %d nextname %d name %s\n", entry.nextID, entry.nextName, entry.name); printf("owner %d creator %d\n", entry.owner, entry.creator); #endif } } else if (!strcmp(op, "add") || !strcmp(op, "au")) { /* scanf("%d %d",&id,&gid); */ if (GetInt32(&id) || GetInt32(&gid)) code = PRBADARG; else code = ubik_PR_AddToGroup(pruclient, 0, id, gid); if (CodeOk(code)) afs_com_err(whoami, code, "on %s %d %d", op, id, gid); } else if (!strcmp(op, "iton")) { lid.idlist_val = (afs_int32 *) malloc(20 * sizeof(afs_int32)); ptr = lid.idlist_val; lid.idlist_len = 0; foo = line; skip(&foo); while ((lid.idlist_len < 20) && (sscanf(foo, "%d", ptr) != EOF)) { lid.idlist_len++; skip(&foo); ptr++; } if (*foo) { fprintf(stderr, "too many values specified; max is %d\n", 20); } lnames.namelist_val = 0; lnames.namelist_len = 0; code = ubik_PR_IDToName(pruclient, 0, &lid, &lnames); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { for (i = 0; i < lnames.namelist_len; i++) { printf("id %d name %s\n", lid.idlist_val[i], lnames.namelist_val[i]); } free(lnames.namelist_val); } free(lid.idlist_val); lid.idlist_val = 0; lid.idlist_len = 0; } else if (!strcmp(op, "ntoi")) { lnames.namelist_val = (prname *) malloc(PR_MAXLIST * PR_MAXNAMELEN); lnames.namelist_len = 0; foo = line; skip(&foo); for (i = 0; ((lnames.namelist_len < PR_MAXLIST) && (sscanf(foo, "%s", lnames.namelist_val[i]) != EOF)); i++) { lnames.namelist_len++; skip(&foo); } if (*foo) { fprintf(stderr, "too many values specified; max is %d\n", PR_MAXLIST); } lid.idlist_val = 0; lid.idlist_len = 0; code = ubik_PR_NameToID(pruclient, 0, &lnames, &lid); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { for (i = 0; i < lid.idlist_len; i++) printf("name %s id %d\n", lnames.namelist_val[i], lid.idlist_val[i]); free(lid.idlist_val); } free(lnames.namelist_val); lnames.namelist_val = 0; lnames.namelist_len = 0; } else if (!strcmp(op, "del")) { /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_Delete(pruclient, 0, id); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); } else if (!strcmp(op, "dg")) { /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_Delete(pruclient, 0, id); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); } else if (!strcmp(op, "rm")) { /* scanf("%d %d",&id,&gid); */ if (GetInt32(&id) || GetInt32(&gid)) code = PRBADARG; else code = ubik_PR_RemoveFromGroup(pruclient, 0, id, gid); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); } #if defined(SUPERGROUPS) else if (!strcmp(op, "lsg")) { alist.prlist_len = 0; alist.prlist_val = 0; /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_ListSuperGroups(pruclient, 0, id, &alist, &over); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { ptr = alist.prlist_val; if (over) { printf("Number of groups greater than PR_MAXGROUPS!\n"); printf("Excess of %d.\n", over); } for (i = 0; i < alist.prlist_len; i++, ptr++) printf("%d\n", *ptr); free(alist.prlist_val); alist.prlist_len = 0; alist.prlist_val = 0; } } #endif /* SUPERGROUPS */ else if (!strcmp(op, "l")) { alist.prlist_len = 0; alist.prlist_val = 0; /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_GetCPS(pruclient, 0, id, &alist, &over); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { ptr = alist.prlist_val; if (over) { printf("Number of groups greater than PR_MAXGROUPS!\n"); printf("Excess of %d.\n", over); } for (i = 0; i < alist.prlist_len; i++, ptr++) printf("%d\n", *ptr); free(alist.prlist_val); alist.prlist_len = 0; alist.prlist_val = 0; } } else if (!strcmp(op, "lh")) { alist.prlist_len = 0; alist.prlist_val = 0; /* scanf("%d",&id); */ if (GetString(name, sizeof(name))) code = PRBADARG; else if (!(hostinfo = gethostbyname(name))) code = PRBADARG; else { hostaddr = (struct in_addr *)hostinfo->h_addr_list[0]; id = ntohl(hostaddr->s_addr); code = ubik_PR_GetHostCPS(pruclient, 0, id, &alist, &over); } if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { ptr = alist.prlist_val; if (over) { printf("Number of groups greater than PR_MAXGROUPS!\n"); printf("Excess of %d.\n", over); } for (i = 0; i < alist.prlist_len; i++, ptr++) printf("%d\n", *ptr); free(alist.prlist_val); alist.prlist_len = 0; alist.prlist_val = 0; } } #if defined(SUPERGROUPS) else if (!strcmp(op, "m")) { alist.prlist_len = 0; alist.prlist_val = 0; /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_ListElements(pruclient, 0, id, &alist, &over); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) { ptr = alist.prlist_val; if (over) { printf("Number of groups greater than PR_MAXGROUPS!\n"); printf("Excess of %d.\n", over); } for (i = 0; i < alist.prlist_len; i++, ptr++) printf("%d\n", *ptr); free(alist.prlist_val); alist.prlist_len = 0; alist.prlist_val = 0; } } #endif /* SUPERGROUPS */ else if (!strcmp(op, "nu")) { /* scanf("%s",name); */ if (GetString(name, sizeof(name))) code = PRBADARG; else code = pr_CreateUser(name, &id); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) printf("Id is %d.\n", id); } else if (!strcmp(op, "ng")) { /* scanf("%s",name); */ if (GetString(name, sizeof(name))) code = PRBADARG; else code = ubik_PR_NewEntry(pruclient, 0, name, 1, oid, &id); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) printf("Id is %d.\n", id); } else if (!strcmp(op, "lm")) { code = ubik_PR_ListMax(pruclient, 0, &id, &gid); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) printf("Max user id is %d, max (really min) group is %d.\n", id, gid); } else if (!strcmp(op, "smu")) { /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_SetMax(pruclient, 0, id, 0); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); } else if (!strcmp(op, "smg")) { /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = ubik_PR_SetMax(pruclient, 0, id, 1); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); } else if (!strcmp(op, "sin")) { /* scanf("%d",&id); */ if (GetInt32(&id)) code = PRBADARG; else code = pr_SIdToName(id, name); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) printf("id %d name %s\n", id, name); } else if (!strcmp(op, "sni")) { /* scanf("%s",name); */ if (GetString(name, sizeof(name))) code = PRBADARG; else code = pr_SNameToId(name, &id); if (CodeOk(code)) printf("%s\n", pr_ErrorMsg(code)); if (code == PRSUCCESS) printf("name %s id %d\n", name, id); } else if (!strcmp(op, "fih")) { char tname[128]; struct PrUpdateEntry uentry; memset(&uentry, 0, sizeof(uentry)); /* scanf("%s",name); */ if (GetString(name, sizeof(name))) { code = PRBADARG; continue; } code = pr_SNameToId(name, &id); if (CodeOk(code)) { printf("%s\n", pr_ErrorMsg(code)); continue; } code = pr_SIdToName(id, tname); if (code == PRSUCCESS) { printf ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n", name, id); /* continue;*/ } uentry.Mask = PRUPDATE_IDHASH; code = ubik_PR_UpdateEntry(pruclient, 0, 0, name, &uentry); if (code) { printf("Failed to update entry %s (err=%d)\n", name, code); continue; } } else if (!strcmp(op, "fnh")) { int tid; struct PrUpdateEntry uentry; memset(&uentry, 0, sizeof(uentry)); /* scanf("%d", &id); */ if (GetInt32(&id)) { code = PRBADARG; continue; } code = pr_SIdToName(id, name); if (CodeOk(code)) { printf("%s\n", pr_ErrorMsg(code)); continue; } code = pr_SNameToId(name, &tid); if (code == PRSUCCESS) { printf ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n", id, name); /* continue;*/ } uentry.Mask = PRUPDATE_NAMEHASH; code = ubik_PR_UpdateEntry(pruclient, 0, id, "_foo_", &uentry); if (code) { printf("Failed to update entry with id %d (err=%d)\n", id, code); continue; } } #if defined(SUPERGROUPS) else if (!strcmp(op, "fih")) { char tname[128]; struct PrUpdateEntry uentry; memset(&uentry, 0, sizeof(uentry)); /* scanf("%s",name); */ if (GetString(name, sizeof(name))) { code = PRBADARG; continue; } code = pr_SNameToId(name, &id); if (CodeOk(code)) { printf("%s\n", pr_ErrorMsg(code)); continue; } code = pr_SIdToName(id, tname); if (code == PRSUCCESS) { printf ("Warning: Id hash for %s (id %d) seems correct at the db; rehashing it anyway\n", name, id); /* continue;*/ } uentry.Mask = PRUPDATE_IDHASH; code = ubik_PR_UpdateEntry(pruclient, 0, 0, name, &uentry); if (code) { printf("Failed to update entry %s (err=%d)\n", name, code); continue; } } else if (!strcmp(op, "fnh")) { int tid; struct PrUpdateEntry uentry; memset(&uentry, 0, sizeof(uentry)); /* scanf("%d", &id); */ if (GetInt32(&id)) { code = PRBADARG; continue; } code = pr_SIdToName(id, name); if (CodeOk(code)) { printf("%s\n", pr_ErrorMsg(code)); continue; } code = pr_SNameToId(name, &tid); if (code == PRSUCCESS) { printf ("Name hash for %d (name is %s) seems correct at the db; rehashing it anyway\n", id, name); /* continue;*/ } uentry.Mask = PRUPDATE_NAMEHASH; code = ubik_PR_UpdateEntry(pruclient, 0, id, "_foo_", &uentry); if (code) { printf("Failed to update entry with id %d (err=%d)\n", id, code); continue; } } #endif /* SUPERGROUPS */ else if (!strcmp(op, "?")) PrintHelp(); else if (!strcmp(op, "q")) exit(0); else printf("Unknown op: '%s'! ? for help\n", op); } }
int main(int argc, char **argv) { char *whoami = argv[0]; char *dbNamePtr = 0; struct afsconf_cell cellinfo_s; struct afsconf_cell *cellinfo = NULL; time_t currentTime; afs_int32 code = 0; afs_uint32 host = ntohl(INADDR_ANY); char clones[MAXHOSTSPERCELL]; struct rx_service *tservice; struct rx_securityClass **securityClasses; afs_int32 numClasses; extern int rx_stackSize; #ifdef AFS_NT40_ENV /* initialize winsock */ if (afs_winsockInit() < 0) { ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0); fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami); exit(1); } #endif #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); sigaction(SIGABRT, &nsa, NULL); #endif memset(&cellinfo_s, 0, sizeof(cellinfo_s)); memset(clones, 0, sizeof(clones)); osi_audit_init(); osi_audit(BUDB_StartEvent, 0, AUD_END); initialize_BUDB_error_table(); initializeArgHandler(); /* Initialize dirpaths */ if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) { #ifdef AFS_NT40_ENV ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0); #endif afs_com_err(whoami, errno, "; Unable to obtain AFS server directory."); exit(2); } memset(globalConfPtr, 0, sizeof(*globalConfPtr)); /* set default configuration values */ strcpy(dbDir, AFSDIR_SERVER_DB_DIRPATH); strcat(dbDir, "/"); globalConfPtr->databaseDirectory = dbDir; globalConfPtr->databaseName = DEFAULT_DBPREFIX; strcpy(cellConfDir, AFSDIR_SERVER_ETC_DIRPATH); globalConfPtr->cellConfigdir = cellConfDir; srandom(1); #ifdef AFS_PTHREAD_ENV SetLogThreadNumProgram( rx_GetThreadNum ); #endif /* process the user supplied args */ helpOption = 1; code = cmd_Dispatch(argc, argv); if (code) ERROR(code); /* exit if there was a help option */ if (helpOption) BUDB_EXIT(0); /* open the log file */ OpenLog(AFSDIR_SERVER_BUDBLOG_FILEPATH); /* open the cell's configuration directory */ LogDebug(4, "opening %s\n", globalConfPtr->cellConfigdir); BU_conf = afsconf_Open(globalConfPtr->cellConfigdir); if (BU_conf == 0) { LogError(code, "Failed getting cell info\n"); afs_com_err(whoami, code, "Failed getting cell info"); ERROR(BUDB_NOCELLS); } code = afsconf_GetLocalCell(BU_conf, lcell, sizeof(lcell)); if (code) { LogError(0, "** Can't determine local cell name!\n"); ERROR(code); } if (globalConfPtr->myHost == 0) { /* if user hasn't supplied a list of servers, extract server * list from the cell's database */ cellinfo = &cellinfo_s; LogDebug(1, "Using server list from %s cell database.\n", lcell); code = afsconf_GetExtendedCellInfo (BU_conf, lcell, 0, cellinfo, clones); if (code) { LogError(0, "Can't read cell information\n"); ERROR(code); } code = convert_cell_to_ubik(cellinfo, &globalConfPtr->myHost, globalConfPtr->serverList); if (code) ERROR(code); } /* initialize audit user check */ osi_audit_set_user_check(BU_conf, BU_IsLocalRealmMatch); /* initialize ubik */ ubik_SetClientSecurityProcs(afsconf_ClientAuth, afsconf_UpToDate, BU_conf); ubik_SetServerSecurityProcs(afsconf_BuildServerSecurityObjects, afsconf_CheckAuth, BU_conf); if (ubik_nBuffers == 0) ubik_nBuffers = 400; LogError(0, "Will allocate %d ubik buffers\n", ubik_nBuffers); asprintf(&dbNamePtr, "%s%s", globalConfPtr->databaseDirectory, globalConfPtr->databaseName); if (dbNamePtr == 0) ERROR(-1); rx_SetRxDeadTime(60); /* 60 seconds inactive before timeout */ if (rxBind) { afs_int32 ccode; if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) { char reason[1024]; ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL, ADDRSPERSITE, reason, AFSDIR_SERVER_NETINFO_FILEPATH, AFSDIR_SERVER_NETRESTRICT_FILEPATH); } else { ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE); } if (ccode == 1) { host = SHostAddrs[0]; rx_InitHost(host, htons(AFSCONF_BUDBPORT)); } } /* Disable jumbograms */ rx_SetNoJumbo(); if (cellinfo) { code = ubik_ServerInitByInfo(globalConfPtr->myHost, htons(AFSCONF_BUDBPORT), cellinfo, clones, dbNamePtr, /* name prefix */ &BU_dbase); } else { code = ubik_ServerInit(globalConfPtr->myHost, htons(AFSCONF_BUDBPORT), globalConfPtr->serverList, dbNamePtr, /* name prefix */ &BU_dbase); } if (code) { LogError(code, "Ubik init failed\n"); afs_com_err(whoami, code, "Ubik init failed"); ERROR(code); } afsconf_BuildServerSecurityObjects(BU_conf, &securityClasses, &numClasses); tservice = rx_NewServiceHost(host, 0, BUDB_SERVICE, "BackupDatabase", securityClasses, numClasses, BUDB_ExecuteRequest); if (tservice == (struct rx_service *)0) { LogError(0, "Could not create backup database rx service\n"); printf("Could not create backup database rx service\n"); BUDB_EXIT(3); } rx_SetMinProcs(tservice, 1); rx_SetMaxProcs(tservice, lwps); rx_SetStackSize(tservice, 10000); /* allow super users to manage RX statistics */ rx_SetRxStatUserOk(BU_rxstat_userok); /* misc. initialization */ /* database dump synchronization */ memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr)); Lock_Init(&dumpSyncPtr->ds_lock); rx_StartServer(0); /* start handling requests */ code = InitProcs(); if (code) ERROR(code); currentTime = time(0); LogError(0, "Ready to process requests at %s\n", ctime(¤tTime)); rx_ServerProc(NULL); /* donate this LWP */ error_exit: osi_audit(BUDB_FinishEvent, code, AUD_END); return (code); }
static long RunHijackTest(struct clientParms *parms, long host, struct rx_securityClass *sc, long si) { #ifndef rx_GetPacketCksum code = RXKST_BADARGS; afs_com_err(whoami, code, "Older versions of Rx don't export packet tracing routines: can't run this HijackTest"); return code; #else long code; struct rx_connection *conn = 0; struct rx_connection *otherConn = 0; #ifdef AFS_PTHREAD_ENV pthread_t pid; #else PROCESS pid; #endif int nResp; /* otherConn responses seen */ long tmp_rc; #ifdef AFS_PTHREAD_ENV pthread_once(&slowCallOnce, SlowCallInit); #endif rx_justReceived = HandleIncoming; rx_almostSent = HandleOutgoing; incomingOps.op = IO_NOOP; outgoingOps.op = OO_NOOP; #define HIJACK_CONN(conn) \ { if (conn) rx_DestroyConnection (conn); \ (conn) = rx_NewConnection(host, htons(RXKST_SERVICEPORT), \ RXKST_SERVICEID, sc, si); \ if (!(conn)) return RXKST_NEWCONNFAILED; \ outgoingOps.client = 1; \ outgoingOps.epoch = (conn)->epoch; \ outgoingOps.cid = (conn)->cid; } HIJACK_CONN(conn); /* First try switching from no packet cksum to sending packet cksum between * calls, and see if server complains. */ outgoingOps.op = OO_ZEROCKSUM; code = FastCall(conn); if (code) { afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM"); return code; } /* The server thinks we're an old style client. Now start sending cksums. * Server shouldn't care. */ outgoingOps.op = OO_NOOP; code = FastCall(conn); if (code) { afs_com_err(whoami, code, "doing FastCall with non-ZEROCKSUM"); return code; } /* The server now thinks we're a new style client, we can't go back now. */ outgoingOps.op = OO_ZEROCKSUM; code = FastCall(conn); if (code == 0) code = RXKST_NOBADCKSUM; if (code != RXKADSEALEDINCON) { afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM"); return code; } else if (!conn->error) { code = RXKST_NOCONNERROR; afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM"); return code; } else code = 0; HIJACK_CONN(conn); /* Now try modifying packet cksum to see if server complains. */ outgoingOps.op = OO_MUNGCKSUM; code = FastCall(conn); if (code == 0) code = RXKST_NOBADCKSUM; if (code != RXKADSEALEDINCON) { afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM"); return code; } else if (!conn->error) { code = RXKST_NOCONNERROR; afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM"); return code; } else code = 0; /* Now make two connection and direct the first challenge on one connection * to the other connection to see if it generates a response. The * retransmitted challenge should allow the call on the first connection to * complete correctly. Part one is to attack a new connection, then attack * it after it has made a call. Part three, just for comparison, attacks a * otherConn while it is making a slow call (and thus has an active call). * Against this attack we have no defense so we expect a challenge in this * case, which the server will discard. */ #define RedirectChallenge(conn,otherConn) \ (incomingOps.epoch = (conn)->epoch, \ incomingOps.cid = (conn)->cid, \ incomingOps.client = 1, \ incomingOps.newEpoch = (otherConn)->epoch, \ incomingOps.newCid = (otherConn)->cid, \ incomingOps.op = IO_REDIRECTCHALLENGE, \ outgoingOps.epoch = (otherConn)->epoch, \ outgoingOps.cid = (otherConn)->cid, \ outgoingOps.client = 1, \ outgoingOps.op = OO_COUNT, \ outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] = 0) HIJACK_CONN(conn); HIJACK_CONN(otherConn) RedirectChallenge(conn, otherConn); code = FastCall(conn); if (code) return code; assert(incomingOps.op == IO_COUNT); /* redirect code was triggered */ if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] > 0) { oracle: code = RXKST_CHALLENGEORACLE; afs_com_err(whoami, code, "misdirecting challenge"); return code; } code = FastCall(otherConn); /* generate some activity here */ if (code) return code; nResp = outgoingOps.counts[RX_PACKET_TYPE_RESPONSE]; assert(nResp >= 1); code = FastCall(conn); if (code) return code; if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] > nResp) goto oracle; HIJACK_CONN(conn); RedirectChallenge(conn, otherConn); /* otherConn was authenticated during part one */ code = FastCall(conn); if (code) return code; assert(incomingOps.op == IO_COUNT); /* redirect code was triggered */ if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] != 0) goto oracle; HIJACK_CONN(conn); RedirectChallenge(conn, otherConn); /* otherConn is still authenticated */ slowCallCode = RXKST_PROCESSCREATED; #ifdef AFS_PTHREAD_ENV { pthread_attr_t tattr; code = pthread_attr_init(&tattr); if (code) { afs_com_err(whoami, code, "can't pthread_attr_init slow call process"); return code; } code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) { afs_com_err(whoami, code, "can't pthread_attr_setdetachstate slow call process"); return code; } code = pthread_create(&pid, &tattr, SlowCall, (void *)otherConn); } #else code = LWP_CreateProcess(SlowCall, 16000, LWP_NORMAL_PRIORITY, (opaque) otherConn, "Slow Call Process", &pid); #endif if (code) { afs_com_err(whoami, code, "can't create slow call process"); return code; } #ifdef AFS_PTHREAD_ENV pthread_mutex_lock(&slowCallLock); while (slowCallCode == RXKST_PROCESSCREATED) pthread_cond_wait(&slowCallCV, &slowCallLock); #else while (slowCallCode == RXKST_PROCESSCREATED) LWP_WaitProcess(&slowCallCode); /* wait for process start */ #endif if (slowCallCode != RXKST_PROCESSRUNNING) { tmp_rc = slowCallCode; #ifdef AFS_PTHREAD_ENV pthread_mutex_unlock(&slowCallLock); #endif return tmp_rc; /* make sure didn't fail immediately */ } assert(incomingOps.op == IO_REDIRECTCHALLENGE); code = FastCall(conn); if (code) return code; assert(incomingOps.op == IO_COUNT); /* redirect code was triggered */ #ifdef AFS_PTHREAD_ENV while (slowCallCode == RXKST_PROCESSRUNNING) pthread_cond_wait(&slowCallCV, &slowCallLock); pthread_mutex_unlock(&slowCallLock); #else while (slowCallCode == RXKST_PROCESSRUNNING) LWP_WaitProcess(&slowCallCode); /* wait for process finish */ #endif if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] != 1) goto oracle; rx_justReceived = 0; rx_almostSent = 0; rx_DestroyConnection(otherConn); rx_DestroyConnection(conn); return code; #endif /* rx_GetPacketCksum */ }
int CommandProc(struct cmd_syndesc *as, void *arock) { char name[MAXKTCNAMELEN]; char instance[MAXKTCNAMELEN]; char cell[MAXKTCREALMLEN]; char realm[MAXKTCREALMLEN]; afs_uint32 serverList[MAXSERVERS]; char *lcell; /* local cellname */ char lrealm[MAXKTCREALMLEN]; /* uppercase copy of local cellname */ int code; int i, dosetpag; Date lifetime; /* requested ticket lifetime */ struct passwd pwent; struct passwd *pw = &pwent; struct passwd *lclpw = &pwent; char passwd[BUFSIZ]; static char rn[] = "klog"; /*Routine name */ static int Pipe = 0; /* reading from a pipe */ static int Silent = 0; /* Don't want error messages */ int explicit; /* servers specified explicitly */ int local; /* explicit cell is same a local one */ int foundPassword = 0; /*Not yet, anyway */ int foundExplicitCell = 0; /*Not yet, anyway */ int writeTicketFile = 0; /* write ticket file to /tmp */ afs_int32 password_expires = -1; char *reason; /* string describing errors */ /* 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 -silent switch */ Silent = (as->parms[aSILENT].items ? 1 : 0); Pipe = (as->parms[aPIPE].items ? 1 : 0); /* Determine if we should also do a setpag based on -setpag switch */ dosetpag = (as->parms[aSETPAG].items ? 1 : 0); if (as->parms[aTMP].items) { writeTicketFile = 1; } 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)); /* XXX the following is just a hack to handle the afscell environment XXX */ (void)afsconf_GetCellInfo((struct afsconf_dir *)0, realm, 0, (struct afsconf_cell *)0); } code = ka_Init(0); if (code || !(lcell = ka_LocalCell())) { nocell: if (!Silent) afs_com_err(rn, code, "Can't get local cell name!"); KLOGEXIT(code); } if ((code = ka_CellToRealm(lcell, lrealm, 0))) goto nocell; 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 (!Silent) { afs_com_err(rn, code, "could not parse server list"); } return code; } explicit = 1; } else
static long CallSimultaneously(u_int threads, opaque rock, long (*proc)(int, opaque)) { long code; int i; #ifdef AFS_PTHREAD_ENV pthread_once(&workerOnce, WorkerInit); #endif workers = 0; for (i = 0; i < threads; i++) { struct worker *w; #ifdef AFS_PTHREAD_ENV pthread_t pid; #else PROCESS pid; #endif assert(i < MAX_CTHREADS); w = (struct worker *)osi_Alloc(sizeof(struct worker)); memset(w, 0, sizeof(*w)); w->next = workers; workers = w; w->index = i; w->exitCode = RXKST_PROCESSRUNNING; w->rock = rock; w->proc = proc; #ifdef AFS_PTHREAD_ENV { pthread_attr_t tattr; code = pthread_attr_init(&tattr); if (code) { afs_com_err(whoami, code, "can't pthread_attr_init worker process"); return code; } code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (code) { afs_com_err(whoami, code, "can't pthread_attr_setdetachstate worker process"); return code; } code = pthread_create(&pid, &tattr, DoWorker, (void *)w); } #else code = LWP_CreateProcess(DoWorker, 16000, LWP_NORMAL_PRIORITY, (opaque) w, "Worker Process", &pid); #endif if (code) { afs_com_err(whoami, code, "can't create worker process"); return code; } } code = 0; /* last non-zero code encountered */ #ifdef AFS_PTHREAD_ENV pthread_mutex_lock(&workerLock); #endif while (workers) { struct worker *w, *prevW, *nextW; prevW = 0; for (w = workers; w; w = nextW) { nextW = w->next; if (w->exitCode != RXKST_PROCESSRUNNING) { if (w->exitCode) { if (code == 0) code = w->exitCode; } if (prevW) prevW->next = w->next; else workers = w->next; osi_Free(w, sizeof(*w)); continue; /* don't bump prevW */ } prevW = w; } #ifdef AFS_PTHREAD_ENV if (workers) pthread_cond_wait(&workerCV, &workerLock); #else if (workers) LWP_WaitProcess(&workers); #endif } #ifdef AFS_PTHREAD_ENV pthread_mutex_unlock(&workerLock); #endif return code; }
afs_int32 pr_Initialize(IN afs_int32 secLevel, IN const char *confDir, IN char *cell) { afs_int32 code; struct rx_connection *serverconns[MAXSERVERS]; struct rx_securityClass *sc = NULL; static struct afsconf_dir *tdir = NULL; /* only do this once */ static char tconfDir[100] = ""; static char tcell[64] = ""; afs_int32 scIndex; afs_int32 secFlags; static struct afsconf_cell info; afs_int32 i; char cellstr[64]; afs_int32 gottdir = 0; afs_int32 refresh = 0; initialize_PT_error_table(); initialize_RXK_error_table(); initialize_ACFG_error_table(); initialize_KTC_error_table(); if (!cell) { if (!tdir) tdir = afsconf_Open(confDir); if (!tdir) { if (confDir && strcmp(confDir, "")) fprintf(stderr, "%s: Could not open configuration directory: %s.\n", whoami, confDir); else fprintf(stderr, "%s: No configuration directory specified.\n", whoami); return -1; } gottdir = 1; code = afsconf_GetLocalCell(tdir, cellstr, sizeof(cellstr)); if (code) { fprintf(stderr, "libprot: Could not get local cell. [%d]\n", code); return code; } cell = cellstr; } if (tdir == NULL || strcmp(confDir, tconfDir) || strcmp(cell, tcell)) { /* * force re-evaluation. we either don't have an afsconf_dir, * the directory has changed or the cell has changed. */ if (tdir && !gottdir) { afsconf_Close(tdir); tdir = NULL; } pruclient = NULL; refresh = 1; } if (refresh) { strncpy(tconfDir, confDir, sizeof(tconfDir)); strncpy(tcell, cell, sizeof(tcell)); if (!gottdir) tdir = afsconf_Open(confDir); if (!tdir) { if (confDir && strcmp(confDir, "")) fprintf(stderr, "libprot: Could not open configuration directory: %s.\n", confDir); else fprintf(stderr, "libprot: No configuration directory specified.\n"); return -1; } code = afsconf_GetCellInfo(tdir, cell, "afsprot", &info); if (code) { fprintf(stderr, "libprot: Could not locate cell %s in %s/%s\n", cell, confDir, AFSDIR_CELLSERVDB_FILE); return code; } } /* If we already have a client and it is at the security level we * want, don't get a new one. Unless the security level is 2 in * which case we will get one (and re-read the key file). */ if (pruclient && (lastLevel == secLevel) && (secLevel != 2)) { return 0; } code = rx_Init(0); if (code) { fprintf(stderr, "libprot: Could not initialize rx.\n"); return code; } /* Most callers use secLevel==1, however, the fileserver uses secLevel==2 * to force use of the KeyFile. secLevel == 0 implies -noauth was * specified. */ if (secLevel == 2) { /* If secLevel is two assume we're on a file server and use * ClientAuthSecure if possible. */ code = afsconf_ClientAuthSecure(tdir, &sc, &scIndex); if (code) afs_com_err(whoami, code, "(calling client secure)\n"); } else if (secLevel > 0) { secFlags = 0; if (secLevel > 1) secFlags |= AFSCONF_SECOPTS_ALWAYSENCRYPT; code = afsconf_ClientAuthToken(&info, secFlags, &sc, &scIndex, NULL); if (code) { afs_com_err(whoami, code, "(getting token)"); if (secLevel > 1) return code; } } if (sc == NULL) { sc = rxnull_NewClientSecurityObject(); scIndex = RX_SECIDX_NULL; } if ((scIndex == RX_SECIDX_NULL) && (secLevel != 0)) fprintf(stderr, "%s: Could not get afs tokens, running unauthenticated\n", whoami); memset(serverconns, 0, sizeof(serverconns)); /* terminate list!!! */ for (i = 0; i < info.numServers; i++) serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port, PRSRV, sc, scIndex); code = ubik_ClientInit(serverconns, &pruclient); if (code) { afs_com_err(whoami, code, "ubik client init failed."); return code; } lastLevel = scIndex; code = rxs_Release(sc); return code; }
static long RunCallTest(struct clientParms *parms, long host, struct rx_securityClass *sc, long si) { long code; #ifndef rx_GetPacketCksum code = RXKST_BADARGS; afs_com_err(whoami, code, "Older versions of Rx don't support Get/Set callNumber Vector procedures: can't run this CallTest"); return code; #else int i, ch; struct rx_connection *conn; long firstCall; afs_int32 callNumbers[RX_MAXCALLS]; long codes[RX_MAXCALLS]; long retCode = 0; /* ret. if nothing fatal goes wrong */ conn = rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc, si); if (!conn) return RXKST_NEWCONNFAILED; /* First check the basic behaviour of call number handling */ code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; for (i = 0; i < RX_MAXCALLS; i++) { if (callNumbers[i] != 0) { fprintf(stderr, "Connection's initial call numbers not zero. call[%d] = %d\n", i, callNumbers[i]); return RXKST_BADCALLNUMBERS; } } code = FastCall(conn); if (code) return code; code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; firstCall = callNumbers[0]; code = FastCall(conn); if (code) return code; code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; if ((callNumbers[0] != firstCall + 1) && ((firstCall == 1) || (firstCall == 2))) { /* The call number after the first call should be one or, more likely, * two (if the call is still DALLYing). Between first and second call, * the call number should have incremented by one. */ fprintf(stderr, "Connection's first channel call number not one. call[%d] = %d\n", 0, callNumbers[0]); return RXKST_BADCALLNUMBERS; } for (i = 1; i < RX_MAXCALLS; i++) { if (callNumbers[i] != 0) { fprintf(stderr, "Connection's other channel call numbers not zero. call[%d] = %d\n", i, callNumbers[i]); return RXKST_BADCALLNUMBERS; } } code = MakeMultiChannelCall(conn, 1, 0, codes); if (code) return code; /* Now try to resend a call that's already been executed by finding a * non-zero call number on a channel other than zero and decrementing it by * one. This should appear to the server as a retransmitted call. Since * this is behaving as a broken client different strange behaviors may be * exhibited by different servers. If the response packet to the original * call is discarded by the time the "retransmitted" call arrives (perhaps * due to high server or client load) there is no way for the server to * respond at all. Further, it seems, that under some cases the connection * will be kept alive indefinitely even though the server has discarded the * "retransmitted" call and is making no effort to reexecute the call. To * handle these, accept either a timeout (-1) or and INCFAILED error here, * also set the connenction HardDeadTime to punt after a reasonable * interval. */ /* short dead time since may we expect some trouble */ rx_SetConnHardDeadTime(conn, 30); code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; for (ch = 1; ch < RX_MAXCALLS; ch++) if (callNumbers[ch] > 1) { callNumbers[ch]--; code = rxi_SetCallNumberVector(conn, callNumbers); if (code) return code; break; } if (ch >= RX_MAXCALLS) /* didn't find any? all DALLYing? */ return RXKST_BADCALLNUMBERS; code = MakeMultiChannelCall(conn, 1, RXKST_INCFAILED, codes); code = CheckCallFailure(conn, codes, code, "retransmitted call"); if (code && !retCode) retCode = code; /* Get a fresh connection, becasue if the above failed as it should the * connection is dead. */ rx_DestroyConnection(conn); conn = rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc, si); if (!conn) return RXKST_NEWCONNFAILED; /* Similarly, but decrement call number by two which should be completely * unmistakeable as a broken or malicious client. */ /* short dead time since may we expect some trouble */ rx_SetConnHardDeadTime(conn, 30); code = MakeMultiChannelCall(conn, 2, 0, codes); if (code) return code; code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; for (ch = 1; ch < RX_MAXCALLS; ch++) if (callNumbers[ch] > 2) { callNumbers[ch] -= 2; code = rxi_SetCallNumberVector(conn, callNumbers); break; } if (ch >= RX_MAXCALLS) /* didn't find any? all DALLYing? */ return RXKST_BADCALLNUMBERS; code = MakeMultiChannelCall(conn, 1, -1, codes); code = CheckCallFailure(conn, codes, code, "duplicate call"); if (code && !retCode) retCode = code; rx_DestroyConnection(conn); conn = rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc, si); if (!conn) return RXKST_NEWCONNFAILED; /* Next, without waiting for the server to discard its state, we will check * to see if the Challenge/Response protocol correctly informs the server * of the client's callNumber state. We do this by artificially increasing * the call numbers of a new connection for all channels beyond zero, * making a call on channel zero, then resetting the call number for the * unused channels back to zero, then making calls on all channels. */ code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; for (i = 0; i < RX_MAXCALLS; i++) { if (callNumbers[i] != 0) return RXKST_BADCALLNUMBERS; callNumbers[i] = 51; /* an arbitrary value... */ } code = rxi_SetCallNumberVector(conn, callNumbers); if (code) return code; code = FastCall(conn); /* use channel 0 */ if (code) return code; code = rxi_GetCallNumberVector(conn, callNumbers); if (code) return code; if (callNumbers[0] != 52) return RXKST_BADCALLNUMBERS; for (i = 1; i < RX_MAXCALLS; i++) { if (callNumbers[i] != 51) return RXKST_BADCALLNUMBERS; callNumbers[i] = 37; /* back up a ways */ } code = rxi_SetCallNumberVector(conn, callNumbers); if (code) return code; /* now try calls on all channels... */ code = MakeMultiChannelCall(conn, 1, -1, codes); code = CheckCallFailure(conn, codes, code, "alternate channel call replay"); if (code && !retCode) retCode = code; rx_DestroyConnection(conn); return retCode; #endif /* rx_GetPacketCksum */ }
void ViceIDToUsername(char *username, char *realm_of_user, char *realm_of_cell, char * cell_to_use, CREDENTIALS *c, int *status, struct ktc_principal *aclient, struct ktc_principal *aserver, struct ktc_token *atoken) { static char lastcell[MAXCELLCHARS+1] = { 0 }; static char confname[512] = { 0 }; char username_copy[BUFSIZ]; afs_int32 viceId; /* AFS uid of user */ if (confname[0] == '\0') { strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname)); confname[sizeof(confname) - 2] = '\0'; } if (dflag) printf("About to resolve name %s to id\n", username); strcpy(lastcell, aserver->cell); if (!pr_Initialize (0, confname, aserver->cell)) { char sname[PR_MAXNAMELEN], *at; strncpy(sname, username, PR_MAXNAMELEN); sname[PR_MAXNAMELEN-1] = '\0'; at = strchr(sname, '@'); if (at && !stricmp(at+1, realm_of_cell)) *at = '\0'; *status = pr_SNameToId (sname, &viceId); } if (dflag) { if (*status) printf("pr_SNameToId Error %s\n", afs_error_message(*status)); else printf("Id %d\n", viceId); } /* * This code is taken from cklog -- it lets people * automatically register with the ptserver in foreign cells */ #ifdef ALLOW_REGISTER if (*status == 0) { if (viceId != ANONYMOUSID) { #else /* ALLOW_REGISTER */ if ((*status == 0) && (viceId != ANONYMOUSID)) #endif /* ALLOW_REGISTER */ { #ifdef AFS_ID_TO_NAME strncpy(username_copy, username, BUFSIZ); snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId); #endif /* AFS_ID_TO_NAME */ } #ifdef ALLOW_REGISTER } else if (strcmp(realm_of_user, realm_of_cell) != 0) { int i; int flags = 0; char * smbname = NULL; if (dflag) { printf("doing first-time registration of %s " "at %s\n", username, cell_to_use); } strncpy(aclient->name, username, MAXKTCNAMELEN - 1); aclient->name[MAXKTCNAMELEN - 1] = '\0'; strcpy(aclient->instance, ""); strncpy(aclient->cell, cell_to_use, MAXKTCREALMLEN - 1); aclient->cell[MAXKTCREALMLEN - 1] = '\0'; for ( i=0; aclient->cell[i]; i++ ) { if ( islower(aclient->cell[i]) ) aclient->cell[i] = toupper(aclient->cell[i]); } smbname = getenv("AFS_SMBNAME"); if ( smbname ) { strncpy(aclient->smbname, smbname, MAXKTCNAMELEN - 1); aclient->smbname[MAXKTCNAMELEN - 1] = '\0'; flags = AFS_SETTOK_LOGON; if (dflag) printf("obtaining tokens for %s\n", aclient->smbname); } if ((*status = ktc_SetToken(aserver, atoken, aclient, flags))) { afs_com_err(progname, *status, "while obtaining tokens for cell %s\n", cell_to_use); *status = AKLOG_TOKEN; return ; } /* * In case you're wondering, we don't need to change the * filename here because we're still connecting to the * same cell -- we're just using a different authentication * level */ if ((*status = pr_Initialize(1L, confname, aserver->cell))) { printf("pr_Initialize Error %s\n", afs_error_message(*status)); return; } /* copy the name because pr_CreateUser lowercases the realm */ strncpy(username_copy, username, BUFSIZ); viceId = 0; *status = pr_CreateUser(username_copy, &viceId); if (*status) { printf("%s: unable to create remote PTS " "user %s in cell %s (status: %s).\n", progname, username_copy, cell_to_use, afs_error_message(*status)); } else { printf("created cross-cell entry for %s (Id %d) at %s\n", username_copy, viceId, cell_to_use); #ifdef AFS_ID_TO_NAME snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId); #endif /* AFS_ID_TO_NAME */ } } } #endif /* ALLOW_REGISTER */ }
int bc_ParseDumpSchedule(void) { char tbuffer[1024]; char dsname[256], period[64]; char *tp; afs_int32 code; udbClientTextP ctPtr; struct bc_dumpSchedule *tds; struct bc_dumpSchedule **ppds, *pds; afs_int32 expDate, expType; FILE *stream; /* initialize locally used variables */ ctPtr = &bc_globalConfig->configText[TB_DUMPSCHEDULE]; stream = ctPtr->textStream; if (ctPtr->textSize == 0) /* nothing defined yet */ return (0); if (stream == NULL) return (BC_INTERNALERROR); rewind(stream); /* check the magic number and version */ tp = fgets(tbuffer, sizeof(tbuffer), stream); if (tp == 0) /* can't read first line - error */ return (BC_INTERNALERROR); else { afs_int32 dsmagic, dsversion; /* read the first line, and then check magic # and version */ code = sscanf(tbuffer, "%d %d", &dsmagic, &dsversion); if ((code != 2) || (dsmagic != BC_SCHEDULE_MAGIC) || (dsversion != BC_SCHEDULE_VERSION) ) { /* invalid or unexpected header - error */ afs_com_err(whoami, 0, "Unable to understand dump schedule file"); return (BC_INTERNALERROR); } } while (1) { /* read all of the lines out */ tp = fgets(tbuffer, sizeof(tbuffer), stream); if (tp == 0) break; /* hit eof? */ code = sscanf(tbuffer, "%s %s %d %d", dsname, period, &expDate, &expType); if (code != 4) { afs_com_err(whoami, 0, "Syntax error in dump schedule file, line is: %s", tbuffer); return (BC_INTERNALERROR); } tds = (struct bc_dumpSchedule *)malloc(sizeof(struct bc_dumpSchedule)); memset(tds, 0, sizeof(*tds)); tds->next = (struct bc_dumpSchedule *)0; tds->name = (char *)malloc(strlen(dsname) + 1); strcpy(tds->name, dsname); tds->expDate = expDate; tds->expType = expType; /* find the end of the schedule list, and append the new item to it */ ppds = &bc_globalConfig->dsched; pds = *ppds; while (pds != 0) { ppds = &pds->next; pds = *ppds; } *ppds = tds; } return 0; }
/* * Log to a cell. If the cell has already been logged to, return without * doing anything. Otherwise, log to it and mark that it has been logged * to. */ static int auth_to_cell(krb5_context context, char *cell, char *realm) { int status = AKLOG_SUCCESS; char username[BUFSIZ]; /* To hold client username structure */ char name[ANAME_SZ]; /* Name of afs key */ char instance[INST_SZ]; /* Instance of afs key */ char realm_of_user[REALM_SZ]; /* Kerberos realm of user */ char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */ char local_cell[MAXCELLCHARS+1]; char cell_to_use[MAXCELLCHARS+1]; /* Cell to authenticate to */ krb5_creds *v5cred = NULL; #ifdef HAVE_KRB4 CREDENTIALS c; #endif struct ktc_principal aserver; struct ktc_principal aclient; struct ktc_token atoken, btoken; struct afsconf_cell ak_cellconfig; /* General information about the cell */ int i; int getLinkedCell = 0; int flags = 0; char * smbname = getenv("AFS_SMBNAME"); /* try to avoid an expensive call to get_cellconfig */ if (cell && ll_string_check(&authedcells, cell)) { if (dflag) printf("Already authenticated to %s (or tried to)\n", cell); return(AKLOG_SUCCESS); } memset(name, 0, sizeof(name)); memset(instance, 0, sizeof(instance)); memset(realm_of_user, 0, sizeof(realm_of_user)); memset(realm_of_cell, 0, sizeof(realm_of_cell)); memset(&ak_cellconfig, 0, sizeof(ak_cellconfig)); /* NULL or empty cell returns information on local cell */ if (status = get_cellconfig(cell, &ak_cellconfig, local_cell)) return(status); linkedCell: if (getLinkedCell) strncpy(cell_to_use, ak_cellconfig.linkedCell, MAXCELLCHARS); else strncpy(cell_to_use, ak_cellconfig.name, MAXCELLCHARS); cell_to_use[MAXCELLCHARS] = 0; if (ll_string_check(&authedcells, cell_to_use)) { if (dflag) printf("Already authenticated to %s (or tried to)\n", cell_to_use); status = AKLOG_SUCCESS; goto done2; } /* * Record that we have attempted to log to this cell. We do this * before we try rather than after so that we will not try * and fail repeatedly for one cell. */ (void)ll_add_string(&authedcells, cell_to_use); if (dflag) printf("Authenticating to cell %s.\n", cell_to_use); /* We use the afs.<cellname> convention here... */ strcpy(name, AFSKEY); strncpy(instance, cell_to_use, sizeof(instance)); instance[sizeof(instance)-1] = '\0'; /* * Extract the session key from the ticket file and hand-frob an * afs style authenticator. */ if (usev5) { /* using krb5 */ int retry = 1; int realm_fallback = 0; if ((status = get_v5_user_realm(context, realm_of_user)) != KSUCCESS) { char * msg; msg = krb5_get_error_message(context, status); fprintf(stderr, "%s: Couldn't determine realm of user: %s\n", progname, msg); krb5_free_error_message(context, msg); status = AKLOG_KERBEROS; goto done; } if ( strchr(name,'.') != NULL && !accept_dotted_usernames()) { fprintf(stderr, "%s: Can't support principal names including a dot.\n", progname); status = AKLOG_MISC; goto done; } try_v5: if (realm && realm[0]) { if (dflag) printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm); status = get_v5cred(context, name, instance, realm, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); strcpy(realm_of_cell, realm); } else { strcpy(realm_of_cell, afs_realm_of_cell5(context, &ak_cellconfig, realm_fallback)); if (retry == 1 && realm_fallback == 0) { /* Only try the realm_of_user once */ status = -1; if (dflag) printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_user); status = get_v5cred(context, name, instance, realm_of_user, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); if (status == 0) { /* we have determined that the client realm * is a valid cell realm */ strcpy(realm_of_cell, realm_of_user); } } if (status != 0 && (!retry || retry && strcmp(realm_of_user,realm_of_cell))) { if (dflag) printf("Getting v5 tickets: %s/%s@%s\n", name, instance, realm_of_cell); status = get_v5cred(context, name, instance, realm_of_cell, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); if (!status && !strlen(realm_of_cell)) copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), v5cred); } } if (!realm_fallback && status == KRB5_ERR_HOST_REALM_UNKNOWN) { realm_fallback = 1; goto try_v5; } else if (status == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) { if (!realm_fallback && !realm_of_cell[0]) { realm_fallback = 1; goto try_v5; } if (dflag) printf("Getting v5 tickets: %s@%s\n", name, realm_of_cell); status = get_v5cred(context, name, "", realm_of_cell, #ifdef HAVE_KRB4 use524 ? &c : NULL, #else NULL, #endif &v5cred); if (!status && !strlen(realm_of_cell)) copy_realm_of_ticket(context, realm_of_cell, sizeof(realm_of_cell), v5cred); } if ( status == KRB5KRB_AP_ERR_MSG_TYPE && retry ) { retry = 0; realm_fallback = 0; goto try_v5; } } else { #ifdef HAVE_KRB4 if (realm && realm[0]) strcpy(realm_of_cell, realm); else strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig)); /* * Try to obtain AFS tickets. Because there are two valid service * names, we will try both, but trying the more specific first. * * afs.<cell>@<realm> * afs@<realm> */ if (dflag) printf("Getting tickets: %s.%s@%s\n", name, instance, realm_of_cell); status = get_cred(name, instance, realm_of_cell, &c); if (status == KDC_PR_UNKNOWN) { if (dflag) printf("Getting tickets: %s@%s\n", name, realm_of_cell); status = get_cred(name, "", realm_of_cell, &c); } #else status = AKLOG_MISC; goto done; #endif } if (status != KSUCCESS) { char * msg = NULL; if (dflag) printf("Kerberos error code returned by get_cred: %d\n", status); if (usev5) { msg = krb5_get_error_message(context, status); } #ifdef HAVE_KRB4 else msg = krb_err_text(status); #endif fprintf(stderr, "%s: Couldn't get %s AFS tickets: %s\n", progname, cell_to_use, msg?msg:"(unknown error)"); if (usev5) krb5_free_error_message(context, msg); status = AKLOG_KERBEROS; goto done; } strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1); strncpy(aserver.instance, AFSINST, MAXKTCNAMELEN - 1); strncpy(aserver.cell, cell_to_use, MAXKTCREALMLEN - 1); if (usev5 && !use524) { /* This code inserts the entire K5 ticket into the token * No need to perform a krb524 translation which is * commented out in the code below */ char * p; int len; const char *un; un = krb5_principal_get_comp_string(context, v5cred->client, 0); strncpy(username, un, MAXKTCNAMELEN - 1); username[MAXKTCNAMELEN - 1] = '\0'; if ( krb5_principal_get_num_comp(context, v5cred->client) > 1 ) { strcat(username, "."); p = username + strlen(username); len = (unsigned int)(MAXKTCNAMELEN - strlen(username) - 1); strncpy(p, krb5_principal_get_comp_string(context, v5cred->client, 1), len); p[len] = '\0'; } memset(&atoken, '\0', sizeof(atoken)); atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; atoken.startTime = v5cred->times.starttime; atoken.endTime = v5cred->times.endtime; if (tkt_DeriveDesKey(v5cred->session.keytype, v5cred->session.keyvalue.data, v5cred->session.keyvalue.length, &atoken.sessionKey)) { status = AKLOG_MISC; goto done; } atoken.ticketLen = v5cred->ticket.length; memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen); } else { #ifdef HAVE_KRB4 strcpy (username, c.pname); if (c.pinst[0]) { strcat(username, "."); strcat(username, c.pinst); } atoken.kvno = c.kvno; atoken.startTime = c.issue_date; /* ticket lifetime is in five-minutes blocks. */ atoken.endTime = c.issue_date + ((unsigned char)c.lifetime * 5 * 60); memcpy(&atoken.sessionKey, c.session, 8); atoken.ticketLen = c.ticket_st.length; memcpy(atoken.ticket, c.ticket_st.dat, atoken.ticketLen); #else status = AKLOG_MISC; goto done; #endif } if (!force && !smbname && !ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient) && atoken.kvno == btoken.kvno && atoken.ticketLen == btoken.ticketLen && !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) { if (dflag) printf("Identical tokens already exist; skipping.\n"); status = AKLOG_SUCCESS; goto done2; } if (noprdb) { if (dflag) printf("Not resolving name %s to id (-noprdb set)\n", username); } else { if (!usev5) { #ifdef HAVE_KRB4 if ((status = krb_get_tf_realm(TKT_FILE, realm_of_user)) != KSUCCESS) { fprintf(stderr, "%s: Couldn't determine realm of user: %s)", progname, krb_err_text(status)); status = AKLOG_KERBEROS; goto done; } #else status = AKLOG_MISC; goto done; #endif } /* For Network Identity Manager append the realm to the name */ strcat(username, "@"); strcat(username, realm_of_user); ViceIDToUsername(username, realm_of_user, realm_of_cell, cell_to_use, #ifdef HAVE_KRB4 &c, #else NULL, #endif &status, &aclient, &aserver, &atoken); } if (dflag) printf("Set username to %s\n", username); /* Reset the "aclient" structure before we call ktc_SetToken. * This structure was first set by the ktc_GetToken call when * we were comparing whether identical tokens already existed. */ strncpy(aclient.name, username, MAXKTCNAMELEN - 1); strcpy(aclient.instance, ""); if (usev5 && !use524) { strncpy(aclient.cell, krb5_principal_get_realm(context, v5cred->client), MAXKTCNAMELEN - 1); aclient.cell[MAXKTCNAMELEN - 1] = '\0'; } #ifdef HAVE_KRB4 else strncpy(aclient.cell, c.realm, MAXKTCREALMLEN - 1); #endif for ( i=0; aclient.cell[i]; i++ ) { if ( islower(aclient.cell[i]) ) aclient.cell[i] = toupper(aclient.cell[i]); } if ( smbname ) { if (dflag) printf("Setting tokens for %s.\n", smbname); strncpy(aclient.smbname, smbname, MAXKTCNAMELEN - 1); aclient.smbname[MAXKTCNAMELEN - 1] = '\0'; flags = AFS_SETTOK_LOGON; } else { if (dflag) printf("Setting tokens.\n"); } if (status = ktc_SetToken(&aserver, &atoken, &aclient, flags)) { afs_com_err(progname, status, "while setting token for cell %s\n", cell_to_use); status = AKLOG_TOKEN; } done2: if (ak_cellconfig.linkedCell && !getLinkedCell) { getLinkedCell = 1; goto linkedCell; } done: #if 0 /* * intentionally leak the linkedCell field because it was allocated * using a different C RTL version. */ if (ak_cellconfig.linkedCell) free(ak_cellconfig.linkedCell); #endif return(status); }
int main(int argc, char **argv) { struct afsconf_dir *dir; char *dirname; int serverPid, clientPid, waited, stat; int code; /* Start the client and the server if requested */ if (argc == 3 ) { if (strcmp(argv[1], "-server") == 0) { globalDir = afsconf_Open(argv[2]); afstest_StartTestRPCService(argv[2], TEST_PORT, TEST_SERVICE_ID, TEST_ExecuteRequest); exit(0); } else if (strcmp(argv[1], "-client") == 0) { startClient(argv[2]); exit(0); } else { printf("Bad option %s\n", argv[1]); exit(1); } } /* Otherwise, do the basic configuration, then start the client and * server */ dirname = afstest_BuildTestConfig(); dir = afsconf_Open(dirname); if (dir == NULL) { fprintf(stderr, "Unable to configure directory.\n"); exit(1); } code = afstest_AddDESKeyFile(dir); if (code) { afs_com_err("superuser-t", code, "while adding new key\n"); exit(1); } printf("Config directory is %s\n", dirname); serverPid = fork(); if (serverPid == -1) { /* Bang */ } else if (serverPid == 0) { execl(argv[0], argv[0], "-server", dirname, NULL); exit(1); } clientPid = fork(); if (clientPid == -1) { kill(serverPid, SIGTERM); waitpid(serverPid, &stat, 0); exit(1); } else if (clientPid == 0) { execl(argv[0], argv[0], "-client", dirname, NULL); } do { waited = waitpid(0, &stat, 0); } while(waited == -1 && errno == EINTR); if (waited == serverPid) { kill(clientPid, SIGTERM); } else if (waited == clientPid) { kill(serverPid, SIGTERM); } waitpid(0, &stat, 0); /* Client and server are both done, so cleanup after everything */ /* unlinkTestConfig(dirname); */ return 0; }
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); } }
int main(int argc, char **argv) { afs_int32 code; afs_uint32 myHost; struct hostent *th; char hostname[64]; struct rx_service *tservice; struct rx_securityClass **securityClasses; afs_int32 numClasses; int lwps = 3; char clones[MAXHOSTSPERCELL]; afs_uint32 host = htonl(INADDR_ANY); struct cmd_syndesc *opts; struct cmd_item *list; char *pr_dbaseName; char *configDir; char *logFile; char *whoami = "ptserver"; char *auditFileName = NULL; char *interface = NULL; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGABRT, &nsa, NULL); sigaction(SIGSEGV, &nsa, NULL); #endif osi_audit_init(); osi_audit(PTS_StartEvent, 0, AUD_END); /* Initialize dirpaths */ if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) { #ifdef AFS_NT40_ENV ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0); #endif fprintf(stderr, "%s: Unable to obtain AFS server directory.\n", argv[0]); exit(2); } pr_dbaseName = strdup(AFSDIR_SERVER_PRDB_FILEPATH); configDir = strdup(AFSDIR_SERVER_ETC_DIRPATH); logFile = strdup(AFSDIR_SERVER_PTLOG_FILEPATH); #if defined(SUPERGROUPS) /* make sure the structures for database records are the same size */ if ((sizeof(struct prentry) != ENTRYSIZE) || (sizeof(struct prentryg) != ENTRYSIZE)) { fprintf(stderr, "The structures for the database records are different" " sizes\n" "struct prentry = %" AFS_SIZET_FMT "\n" "struct prentryg = %" AFS_SIZET_FMT "\n" "ENTRYSIZE = %d\n", sizeof(struct prentry), sizeof(struct prentryg), ENTRYSIZE); PT_EXIT(1); } #endif cmd_DisableAbbreviations(); cmd_DisablePositionalCommands(); opts = cmd_CreateSyntax(NULL, NULL, NULL, NULL); /* ptserver specific options */ cmd_AddParmAtOffset(opts, OPT_database, "-database", CMD_SINGLE, CMD_OPTIONAL, "database file"); cmd_AddParmAlias(opts, OPT_database, "db"); cmd_AddParmAtOffset(opts, OPT_access, "-default_access", CMD_SINGLE, CMD_OPTIONAL, "default access flags for new entries"); #if defined(SUPERGROUPS) cmd_AddParmAtOffset(opts, OPT_groupdepth, "-groupdepth", CMD_SINGLE, CMD_OPTIONAL, "max search depth for supergroups"); cmd_AddParmAlias(opts, OPT_groupdepth, "depth"); #endif cmd_AddParmAtOffset(opts, OPT_restricted, "-restricted", CMD_FLAG, CMD_OPTIONAL, "enable restricted mode"); /* general server options */ cmd_AddParmAtOffset(opts, OPT_auditlog, "-auditlog", CMD_SINGLE, CMD_OPTIONAL, "location of audit log"); cmd_AddParmAtOffset(opts, OPT_auditiface, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL, "interface to use for audit logging"); cmd_AddParmAtOffset(opts, OPT_config, "-config", CMD_SINGLE, CMD_OPTIONAL, "configuration location"); cmd_AddParmAtOffset(opts, OPT_debug, "-d", CMD_SINGLE, CMD_OPTIONAL, "debug level"); cmd_AddParmAtOffset(opts, OPT_logfile, "-logfile", CMD_SINGLE, CMD_OPTIONAL, "location of logfile"); cmd_AddParmAtOffset(opts, OPT_threads, "-p", CMD_SINGLE, CMD_OPTIONAL, "number of threads"); #if !defined(AFS_NT40_ENV) cmd_AddParmAtOffset(opts, OPT_syslog, "-syslog", CMD_SINGLE_OR_FLAG, CMD_OPTIONAL, "log to syslog"); #endif /* rx options */ cmd_AddParmAtOffset(opts, OPT_peer, "-enable_peer_stats", CMD_FLAG, CMD_OPTIONAL, "enable RX transport statistics"); cmd_AddParmAtOffset(opts, OPT_process, "-enable_process_stats", CMD_FLAG, CMD_OPTIONAL, "enable RX RPC statistics"); cmd_AddParmAtOffset(opts, OPT_rxbind, "-rxbind", CMD_FLAG, CMD_OPTIONAL, "bind only to the primary interface"); cmd_AddParmAtOffset(opts, OPT_rxmaxmtu, "-rxmaxmtu", CMD_SINGLE, CMD_OPTIONAL, "maximum MTU for RX"); /* rxkad options */ cmd_AddParmAtOffset(opts, OPT_dotted, "-allow-dotted-principals", CMD_FLAG, CMD_OPTIONAL, "permit Kerberos 5 principals with dots"); code = cmd_Parse(argc, argv, &opts); if (code) PT_EXIT(1); cmd_OptionAsString(opts, OPT_config, &configDir); cmd_OpenConfigFile(AFSDIR_SERVER_CONFIG_FILE_FILEPATH); cmd_SetCommandName("ptserver"); if (cmd_OptionAsList(opts, OPT_access, &list) == 0) { prp_user_default = prp_access_mask(list->data); if (list->next == NULL || list->next->data == NULL) { fprintf(stderr, "Missing second argument for -default_access\n"); PT_EXIT(1); } prp_group_default = prp_access_mask(list->next->data); } #if defined(SUPERGROUPS) cmd_OptionAsInt(opts, OPT_groupdepth, &depthsg); #endif cmd_OptionAsFlag(opts, OPT_restricted, &restricted); /* general server options */ cmd_OptionAsString(opts, OPT_auditlog, &auditFileName); if (cmd_OptionAsString(opts, OPT_auditiface, &interface) == 0) { if (osi_audit_interface(interface)) { printf("Invalid audit interface '%s'\n", interface); PT_EXIT(1); } free(interface); } cmd_OptionAsInt(opts, OPT_debug, &LogLevel); cmd_OptionAsString(opts, OPT_database, &pr_dbaseName); cmd_OptionAsString(opts, OPT_logfile, &logFile); if (cmd_OptionAsInt(opts, OPT_threads, &lwps) == 0) { if (lwps > 64) { /* maximum of 64 */ printf("Warning: '-p %d' is too big; using %d instead\n", lwps, 64); lwps = 64; } else if (lwps < 3) { /* minimum of 3 */ printf("Warning: '-p %d' is too small; using %d instead\n", lwps, 3); lwps = 3; } } #ifndef AFS_NT40_ENV if (cmd_OptionPresent(opts, OPT_syslog)) { serverLogSyslog = 1; cmd_OptionAsInt(opts, OPT_syslog, &serverLogSyslogFacility); } #endif /* rx options */ if (cmd_OptionPresent(opts, OPT_peer)) rx_enablePeerRPCStats(); if (cmd_OptionPresent(opts, OPT_process)) rx_enableProcessRPCStats(); cmd_OptionAsFlag(opts, OPT_rxbind, &rxBind); cmd_OptionAsInt(opts, OPT_rxmaxmtu, &rxMaxMTU); /* rxkad options */ cmd_OptionAsFlag(opts, OPT_dotted, &rxkadDisableDotCheck); cmd_FreeOptions(&opts); if (auditFileName) { osi_audit_file(auditFileName); osi_audit(PTS_StartEvent, 0, AUD_END); } #ifndef AFS_NT40_ENV serverLogSyslogTag = "ptserver"; #endif OpenLog(logFile); /* set up logging */ SetupLogSignals(); prdir = afsconf_Open(configDir); if (!prdir) { fprintf(stderr, "ptserver: can't open configuration directory.\n"); PT_EXIT(1); } if (afsconf_GetNoAuthFlag(prdir)) printf("ptserver: running unauthenticated\n"); #ifdef AFS_NT40_ENV /* initialize winsock */ if (afs_winsockInit() < 0) { ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0); fprintf(stderr, "ptserver: couldn't initialize winsock. \n"); PT_EXIT(1); } #endif /* get this host */ gethostname(hostname, sizeof(hostname)); th = gethostbyname(hostname); if (!th) { fprintf(stderr, "ptserver: couldn't get address of this host.\n"); PT_EXIT(1); } memcpy(&myHost, th->h_addr, sizeof(afs_uint32)); /* get list of servers */ code = afsconf_GetExtendedCellInfo(prdir, NULL, "afsprot", &info, clones); if (code) { afs_com_err(whoami, code, "Couldn't get server list"); PT_EXIT(2); } /* initialize audit user check */ osi_audit_set_user_check(prdir, pr_IsLocalRealmMatch); /* initialize ubik */ ubik_SetClientSecurityProcs(afsconf_ClientAuth, afsconf_UpToDate, prdir); ubik_SetServerSecurityProcs(afsconf_BuildServerSecurityObjects, afsconf_CheckAuth, prdir); /* The max needed is when deleting an entry. A full CoEntry deletion * required removal from 39 entries. Each of which may refers to the entry * being deleted in one of its CoEntries. If a CoEntry is freed its * predecessor CoEntry will be modified as well. Any freed blocks also * modifies the database header. Counting the entry being deleted and its * CoEntry this adds up to as much as 1+1+39*3 = 119. If all these entries * and the header are in separate Ubik buffers then 120 buffers may be * required. */ ubik_nBuffers = 120 + /*fudge */ 40; if (rxBind) { afs_int32 ccode; if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || AFSDIR_SERVER_NETINFO_FILEPATH) { char reason[1024]; ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL, ADDRSPERSITE, reason, AFSDIR_SERVER_NETINFO_FILEPATH, AFSDIR_SERVER_NETRESTRICT_FILEPATH); } else { ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE); } if (ccode == 1) { host = SHostAddrs[0]; /* the following call is idempotent so if/when it gets called * again by the ubik init stuff, it doesn't really matter * -- klm */ rx_InitHost(host, htons(AFSCONF_PROTPORT)); } } /* Disable jumbograms */ rx_SetNoJumbo(); if (rxMaxMTU != -1) { if (rx_SetMaxMTU(rxMaxMTU) != 0) { printf("rxMaxMTU %d is invalid\n", rxMaxMTU); PT_EXIT(1); } } code = ubik_ServerInitByInfo(myHost, htons(AFSCONF_PROTPORT), &info, clones, pr_dbaseName, &dbase); if (code) { afs_com_err(whoami, code, "Ubik init failed"); PT_EXIT(2); } #if defined(SUPERGROUPS) pt_hook_write(); #endif afsconf_BuildServerSecurityObjects(prdir, &securityClasses, &numClasses); tservice = rx_NewServiceHost(host, 0, PRSRV, "Protection Server", securityClasses, numClasses, PR_ExecuteRequest); if (tservice == (struct rx_service *)0) { fprintf(stderr, "ptserver: Could not create new rx service.\n"); PT_EXIT(3); } rx_SetMinProcs(tservice, 2); rx_SetMaxProcs(tservice, lwps); if (rxkadDisableDotCheck) { rx_SetSecurityConfiguration(tservice, RXS_CONFIG_FLAGS, (void *)RXS_CONFIG_FLAGS_DISABLE_DOTCHECK); } tservice = rx_NewServiceHost(host, 0, RX_STATS_SERVICE_ID, "rpcstats", securityClasses, numClasses, RXSTATS_ExecuteRequest); if (tservice == (struct rx_service *)0) { fprintf(stderr, "ptserver: Could not create new rx service.\n"); PT_EXIT(3); } rx_SetMinProcs(tservice, 2); rx_SetMaxProcs(tservice, 4); /* allow super users to manage RX statistics */ rx_SetRxStatUserOk(pr_rxstat_userok); LogCommandLine(argc, argv, "ptserver", #if defined(SUPERGROUPS) "1.1", #else "1.0", #endif "Starting AFS", FSLog); rx_StartServer(1); osi_audit(PTS_FinishEvent, -1, AUD_END); exit(0); }
static int WorkerBee(struct cmd_syndesc *as, void *arock) { afs_int32 code; char *dbFile; char *outFile; afs_int32 index; struct stat info; struct kaheader header; int nentries, i, j, count; int *entrys; struct kaentry entry; dbFile = as->parms[0].items->data; /* -database */ listuheader = (as->parms[1].items ? 1 : 0); /* -uheader */ listkheader = (as->parms[2].items ? 1 : 0); /* -kheader */ listentries = (as->parms[3].items ? 1 : 0); /* -entries */ verbose = (as->parms[4].items ? 1 : 0); /* -verbose */ outFile = (as->parms[5].items ? as->parms[5].items->data : NULL); /* -rebuild */ if (outFile) { out = fopen(outFile, "w"); if (!out) { afs_com_err(whoami, errno, "opening output file %s", outFile); exit(7); } } else out = 0; fd = open(dbFile, O_RDONLY, 0); if (fd < 0) { afs_com_err(whoami, errno, "opening database file %s", dbFile); exit(6); } code = fstat(fd, &info); if (code) { afs_com_err(whoami, errno, "stat'ing file %s", dbFile); exit(6); } if ((info.st_size - UBIK_HEADERSIZE) % UBIK_BUFFERSIZE) fprintf(stderr, "DATABASE SIZE INCONSISTENT: was %d, should be (n*%d + %d), for integral n\n", (int) info.st_size, UBIK_BUFFERSIZE, UBIK_HEADERSIZE); readUbikHeader(); readDB(0, &header, sizeof(header)); code = CheckHeader(&header); if (listkheader) PrintHeader(&header); nentries = (info.st_size - (UBIK_HEADERSIZE + header.headerSize)) / sizeof(struct kaentry); entrys = calloc(nentries, sizeof(int)); for (i = 0, index = sizeof(header); i < nentries; i++, index += sizeof(struct kaentry)) { readDB(index, &entry, sizeof(entry)); if (index >= header.eofPtr) { entrys[i] |= 0x8; } else if (listentries) { PrintEntry(index, &entry); } if (entry.flags & KAFNORMAL) { entrys[i] |= 0x1; /* user entry */ if (strlen(entry.userID.name) == 0) { if (verbose) printf("Entry %d has zero length name\n", i); continue; } if (!DES_check_key_parity(ktc_to_cblock(&entry.key)) || DES_is_weak_key(ktc_to_cblock(&entry.key))) { fprintf(stderr, "Entry %d, %s, has bad key\n", i, EntryName(&entry)); continue; } if (out) { RebuildEntry(&entry); } } else if (entry.flags & KAFFREE) { entrys[i] |= 0x2; /* free entry */ } else if (entry.flags & KAFOLDKEYS) { entrys[i] |= 0x4; /* old keys block */ /* Should check the structure of the oldkeys block? */ } else { if (index < header.eofPtr) { fprintf(stderr, "Entry %d is unrecognizable\n", i); } } } /* Follow the hash chains */ for (j = 0; j < HASHSIZE; j++) { for (index = header.nameHash[j]; index; index = entry.next) { readDB(index, &entry, sizeof(entry)); /* check to see if the name is hashed correctly */ i = NameHash(&entry); if (i != j) { fprintf(stderr, "Entry %" AFS_SIZET_FMT ", %s, found in hash chain %d (should be %d)\n", ((index - sizeof(struct kaheader)) / sizeof(struct kaentry)), EntryName(&entry), j, i); } /* Is it on another hash chain or circular hash chain */ i = (index - header.headerSize) / sizeof(entry); if (entrys[i] & 0x10) { fprintf(stderr, "Entry %d, %s, hash index %d, was found on another hash chain\n", i, EntryName(&entry), j); if (entry.next) fprintf(stderr, "Skipping rest of hash chain %d\n", j); else fprintf(stderr, "No next entry in hash chain %d\n", j); code++; break; } entrys[i] |= 0x10; /* On hash chain */ } } /* Follow the free pointers */ count = 0; for (index = header.freePtr; index; index = entry.next) { readDB(index, &entry, sizeof(entry)); /* Is it on another chain or circular free chain */ i = (index - header.headerSize) / sizeof(entry); if (entrys[i] & 0x20) { fprintf(stderr, "Entry %d, %s, already found on free chain\n", i, EntryName(&entry)); fprintf(stderr, "Skipping rest of free chain\n"); code++; break; } entrys[i] |= 0x20; /* On free chain */ count++; } if (verbose) printf("Found %d free entries\n", count); /* Follow the oldkey blocks */ count = 0; for (index = header.kvnoPtr; index; index = entry.next) { readDB(index, &entry, sizeof(entry)); /* Is it on another chain or circular free chain */ i = (index - header.headerSize) / sizeof(entry); if (entrys[i] & 0x40) { fprintf(stderr, "Entry %d, %s, already found on olkeys chain\n", i, EntryName(&entry)); fprintf(stderr, "Skipping rest of oldkeys chain\n"); code++; break; } entrys[i] |= 0x40; /* On free chain */ count++; } if (verbose) printf("Found %d oldkey blocks\n", count); /* Now recheck all the blocks and see if they are allocated correctly * 0x1 --> User Entry 0x10 --> On hash chain * 0x2 --> Free Entry 0x20 --> On Free chain * 0x4 --> OldKeys Entry 0x40 --> On Oldkeys chain * 0x8 --> Past EOF */ for (i = 0; i < nentries; i++) { j = entrys[i]; if (j & 0x1) { /* user entry */ if (!(j & 0x10)) badEntry(j, i); /* on hash chain? */ else if (j & 0xee) badEntry(j, i); /* anything else? */ } else if (j & 0x2) { /* free entry */ if (!(j & 0x20)) badEntry(j, i); /* on free chain? */ else if (j & 0xdd) badEntry(j, i); /* anything else? */ } else if (j & 0x4) { /* oldkeys entry */ if (!(j & 0x40)) badEntry(j, i); /* on oldkeys chain? */ else if (j & 0xbb) badEntry(j, i); /* anything else? */ } else if (j & 0x8) { /* past eof */ if (j & 0xf7) badEntry(j, i); /* anything else? */ } else badEntry(j, i); /* anything else? */ } exit(code != 0); }
/* vldbClientInit * Initialize a client for the vl ubik database. */ int vldbClientInit(int noAuthFlag, int localauth, char *cellName, struct ubik_client **cstruct, time_t *expires) { afs_int32 code = 0; struct afsconf_dir *acdir; struct rx_securityClass *sc; afs_int32 i, scIndex = RX_SECIDX_NULL; struct afsconf_cell info; struct rx_connection *serverconns[VLDB_MAXSERVERS]; afsconf_secflags secFlags; const char *confdir; secFlags = parseSecFlags(noAuthFlag, localauth, &confdir); secFlags |= AFSCONF_SECOPTS_FALLBACK_NULL; /* This just preserves old behaviour of using the default cell when * passed an empty string */ if (cellName && cellName[0] == '\0') cellName = NULL; /* Find out about the given cell */ acdir = afsconf_Open(confdir); if (!acdir) { afs_com_err(whoami, 0, "Can't open configuration directory '%s'", confdir); ERROR(BC_NOCELLCONFIG); } code = afsconf_GetCellInfo(acdir, cellName, AFSCONF_VLDBSERVICE, &info); if (code) { afs_com_err(whoami, code, "; Can't find cell %s's hosts in %s", cellName, acdir->cellservDB); ERROR(BC_NOCELLCONFIG); } code = afsconf_PickClientSecObj(acdir, secFlags, &info, cellName, &sc, &scIndex, expires); if (code) { afs_com_err(whoami, code, "(configuring connection security)"); ERROR(BC_NOCELLCONFIG); } if (scIndex == RX_SECIDX_NULL && !noAuthFlag) afs_com_err(whoami, 0, "Can't get tokens - running unauthenticated"); /* tell UV module about default authentication */ UV_SetSecurity(sc, scIndex); if (info.numServers > VLDB_MAXSERVERS) { afs_com_err(whoami, 0, "Warning: %d VLDB servers exist for cell '%s', can only remember the first %d", info.numServers, cellName, VLDB_MAXSERVERS); info.numServers = VLDB_MAXSERVERS; } for (i = 0; i < info.numServers; i++) serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, info.hostAddr[i].sin_port, USER_SERVICE_ID, sc, scIndex); serverconns[i] = 0; *cstruct = 0; code = ubik_ClientInit(serverconns, cstruct); if (code) { afs_com_err(whoami, code, "; Can't initialize ubik connection to vldb"); ERROR(code); } error_exit: if (acdir) afsconf_Close(acdir); return (code); }
afs_int32 uss_kauth_AddUser(char *a_user, char *a_passwd) { /*uss_kauth_AddUser */ #ifdef USS_KAUTH_DB static char rn[] = "uss_kauth_AddUser"; /*Routine name */ #endif struct ktc_encryptionKey ktc_key; EncryptionKey key; afs_int32 code; if (uss_SkipKaserver) { /* * Don't talk to the kaserver; assume calls succeded and simply return. * Amasingly people want to update it (most likely kerberos) themselves... */ if (uss_verbose) printf ("[Skip Kaserver option - Adding of user %s in Authentication DB not done]\n", a_user); return 0; } /* * Make sure the module has been initialized before we start trying * to talk to AuthServers. */ if (!initDone) { code = InitThisModule(); if (code) exit(code); } /* * Given the (unencrypted) password and cell, generate a key to * pass to the AuthServer. */ ka_StringToKey(a_passwd, uss_Cell, &ktc_key); memcpy(&key, &ktc_key, sizeof(key)); /* XXX - we could just cast */ if (!uss_DryRun) { if (uss_verbose) fprintf(stderr, "Adding user '%s' to the Authentication DB\n", a_user); #ifdef USS_KAUTH_DB_INSTANCE fprintf(stderr, "%s: KAM_CreateUser: user='******', CreatorInstance='%s', %d bytes\n", rn, a_user, CreatorInstance, strlen(CreatorInstance)); #endif /* USS_KAUTH_DB_INSTANCE */ code = ubik_KAM_CreateUser(uconn_kauthP, 0, a_user, UserInstance, /*set by CheckUsername() */ key); if (code) { if (code == KAEXIST) { if (uss_verbose) fprintf(stderr, "%s: Warning: User '%s' already in Authentication DB\n", uss_whoami, a_user); } else { afs_com_err(uss_whoami, code, "while adding user '%s' to Authentication DB", a_user); #ifdef USS_KAUTH_DB printf("%s: Error code from KAM_CreateUser: %d\n", rn, code); #endif /* USS_KAUTH_DB */ return (code); } } /*KAM_CreateUser failed */ } /*Not a dry run */ else fprintf(stderr, "\t[Dry run - user '%s' NOT added to Authentication DB]\n", a_user); return (0); } /*uss_kauth_AddUser */