static int kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst, char *tcell, struct rx_identity **identity) { char tcell_l[MAXKTCREALMLEN] = ""; char *tmp; int code; afs_int32 islocal; int flag; /* generate lowercased version of cell name */ if (tcell) { strcpy(tcell_l, tcell); tmp = tcell_l; while (*tmp) { *tmp = tolower(*tmp); tmp++; } } code = afsconf_IsLocalRealmMatch(adir, &islocal, tname, tinst, tcell); if (code) { return 0; } /* start with no authorization */ flag = 0; /* localauth special case */ if ((tinst == NULL || strlen(tinst) == 0) && (tcell == NULL || strlen(tcell) == 0) && !strcmp(tname, AUTH_SUPERUSER)) { if (identity) *identity = rx_identity_new(RX_ID_KRB4, AFS_LOCALAUTH_NAME, AFS_LOCALAUTH_NAME, AFS_LOCALAUTH_LEN); flag = 1; /* cell of connection matches local cell or one of the realms */ } else if (islocal) { if (CompFindUser(adir, tname, ".", tinst, NULL, identity)) { flag = 1; } /* cell of conn doesn't match local cell or realm */ } else { if (CompFindUser(adir, tname, ".", tinst, tcell, identity)) { flag = 1; } else if (CompFindUser(adir, tname, ".", tinst, tcell_l, identity)) { flag = 1; } } return flag; }
/* special CompFindUser routine that builds up a princ and then calls finduser on it. If found, returns char * to user string, otherwise returns NULL. The resulting string should be immediately copied to other storage prior to release of mutex. */ static int CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst, char *realm, struct rx_identity **identity) { static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3]; struct rx_identity *testId; /* always must have name */ if (!name || !name[0]) { return 0; } if (strlcpy(fullname, name, sizeof(fullname)) >= sizeof(fullname)) return 0; /* might have instance */ if (inst && inst[0]) { if (!sep || !sep[0]) { return 0; } if (strlcat(fullname, sep, sizeof(fullname)) >= sizeof(fullname)) return 0; if (strlcat(fullname, inst, sizeof(fullname)) >= sizeof(fullname)) return 0; } /* might have realm */ if (realm && realm[0]) { if (strlcat(fullname, "@", sizeof(fullname)) >= sizeof(fullname)) return 0; if (strlcat(fullname, realm, sizeof(fullname)) >= sizeof(fullname)) return 0; } testId = rx_identity_new(RX_ID_KRB4, fullname, fullname, strlen(fullname)); if (afsconf_IsSuperIdentity(adir, testId)) { if (identity) *identity = testId; else rx_identity_free(&testId); return 1; } rx_identity_free(&testId); return 0; }
int afsconf_AddUser(struct afsconf_dir *adir, char *aname) { struct rx_identity *user; int code; user = rx_identity_new(RX_ID_KRB4, aname, aname, strlen(aname)); if (user == NULL) return ENOMEM; code = afsconf_AddIdentity(adir, user); rx_identity_free(&user); return code; }
int afsconf_DeleteUser(struct afsconf_dir *adir, char *name) { struct rx_identity *user; int code; user = rx_identity_new(RX_ID_KRB4, name, name, strlen(name)); if (!user) return ENOMEM; code = afsconf_DeleteIdentity(adir, user); rx_identity_free(&user); return code; }
/*! * Check whether the user authenticated on a given RX call is a super * user or not. If they are, return a pointer to the identity of that * user. * * @param[in] adir * The configuration directory currently in use * @param[in] acall * The RX call whose authenticated identity is being checked * @param[out] identity * The RX identity of the user. Caller must free this structure. * @returns * True if the user is a super user, or if the server is running * in noauth mode. Otherwise, false. */ afs_int32 afsconf_SuperIdentity(struct afsconf_dir *adir, struct rx_call *acall, struct rx_identity **identity) { struct rx_connection *tconn; afs_int32 code; int flag; LOCK_GLOBAL_MUTEX; if (!adir) { UNLOCK_GLOBAL_MUTEX; return 0; } if (afsconf_GetNoAuthFlag(adir)) { if (identity) *identity = rx_identity_new(RX_ID_KRB4, AFS_NOAUTH_NAME, AFS_NOAUTH_NAME, AFS_NOAUTH_LEN); UNLOCK_GLOBAL_MUTEX; return 1; } tconn = rx_ConnectionOf(acall); code = rx_SecurityClassOf(tconn); if (code == RX_SECIDX_NULL) { UNLOCK_GLOBAL_MUTEX; return 0; /* not authenticated at all, answer is no */ } else if (code == RX_SECIDX_VAB) { /* bcrypt tokens */ UNLOCK_GLOBAL_MUTEX; return 0; /* not supported any longer */ } else if (code == RX_SECIDX_KAD) { flag = rxkadSuperUser(adir, acall, identity); UNLOCK_GLOBAL_MUTEX; return flag; } else { /* some other auth type */ UNLOCK_GLOBAL_MUTEX; return 0; /* mysterious, just say no */ } }
void startClient(char *configPath) { struct afsconf_dir *dir; struct rx_identity *testId, *anotherId, *extendedId, *dummy; struct rx_securityClass *class; struct rx_connection *conn; afs_uint32 startTime; char ubuffer[256]; afs_int32 classIndex; int code; struct hostent *he; afs_uint32 addr; afs_int32 result; char *string = NULL; plan(63); dir = afsconf_Open(configPath); ok(dir!=NULL, "Configuration directory opened sucessfully by client"); /* Add a normal user to the super user file */ ok(afsconf_AddUser(dir, "test") == 0, "Adding a simple user works"); testId = rx_identity_new(RX_ID_KRB4, "test", "test", strlen("test")); /* Check that they are a super user */ ok(afsconf_IsSuperIdentity(dir, testId), "User added with old i/face is identitifed as super user"); /* Check that nobody else is */ ok(!afsconf_IsSuperIdentity(dir, rx_identity_new(RX_ID_KRB4, "testy", "testy", strlen("testy"))), "Additional users are not super users"); ok(afsconf_AddUser(dir, "test") == EEXIST, "Adding a user that already exists fails"); ok(afsconf_AddIdentity(dir, testId) == EEXIST, "Adding an identity that already exists fails"); anotherId = rx_identity_new(RX_ID_KRB4, "another", "another", strlen("another")); /* Add another normal user, but using the extended interface */ ok(afsconf_AddIdentity(dir, anotherId) == 0, "Adding a KRB4 identity works"); /* Check that they are a super user */ ok(afsconf_IsSuperIdentity(dir, anotherId), "User added with new i/face is identitifed as super user"); ok(afsconf_AddIdentity(dir, anotherId) == EEXIST, "Adding a KRB4 identity that already exists fails"); /* Add an extended user to the super user file */ extendedId = rx_identity_new(RX_ID_GSS, "*****@*****.**", "\x04\x01\x00\x0B\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x00\x00\x00\[email protected]", 35); ok(afsconf_AddIdentity(dir, extendedId) == 0, "Adding a GSSAPI identity works"); /* Check that they are now special */ ok(afsconf_IsSuperIdentity(dir, extendedId), "Added GSSAPI identity is a super user"); /* Check that display name isn't used for matches */ ok(!afsconf_IsSuperIdentity(dir, rx_identity_new(RX_ID_GSS, "*****@*****.**", "abcdefghijklmnopqrstuvwxyz123456789", 35)), "Display name is not used for extended matches"); ok(afsconf_AddIdentity(dir, extendedId) == EEXIST, "Adding GSSAPI identity twice fails"); /* Add a final normal user, so we can check that iteration works */ /* Add a normal user to the super user file */ ok(afsconf_AddUser(dir, "test2") == 0, "Adding another simple user works"); testOriginalIterator(dir, 0, "test"); testOriginalIterator(dir, 1, "another"); testOriginalIterator(dir, 2, "test2"); ok(afsconf_GetNthUser(dir, 3, ubuffer, sizeof ubuffer) != 0, "Reading past the end of the superuser list fails"); testNewIterator(dir, 0, testId); testNewIterator(dir, 1, anotherId); testNewIterator(dir, 2, extendedId); testNewIterator(dir, 3, rx_identity_new(RX_ID_KRB4, "test2", "test2", strlen("test2"))); ok(afsconf_GetNthIdentity(dir, 4, &dummy) != 0, "Reading past the end of the superuser list fails"); ok(afsconf_DeleteUser(dir, "notthere") != 0, "Deleting a user that doesn't exist fails"); /* Delete the normal user */ ok(afsconf_DeleteUser(dir, "another") == 0, "Deleting normal user works"); ok(!afsconf_IsSuperIdentity(dir, anotherId), "Deleted user is no longer super user"); ok(afsconf_IsSuperIdentity(dir, testId) && afsconf_IsSuperIdentity(dir, extendedId), "Other identities still are"); ok(afsconf_DeleteIdentity(dir, extendedId) == 0, "Deleting identity works"); ok(!afsconf_IsSuperIdentity(dir, extendedId), "Deleted identity is no longer special"); /* Now, what happens if we're doing something over the network instead */ code = rx_Init(0); is_int(code, 0, "Initialised RX"); /* Fake up an rx ticket. Note that this will be for the magic 'superuser' */ code = afsconf_ClientAuth(dir, &class, &classIndex); is_int(code, 0, "Can successfully create superuser token"); /* Start a connection to our test service with it */ he = gethostbyname("localhost"); if (!he) { printf("Couldn't look up server hostname"); exit(1); } memcpy(&addr, he->h_addr, sizeof(afs_uint32)); conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class, classIndex); /* There's nothing in the list, so this just succeeds because we can */ code = TEST_CanI(conn, &result); is_int(0, code, "Can run a simple RPC"); code = TEST_WhoAmI(conn, &string); is_int(0, code, "Can get identity back"); is_string("<LocalAuth>", string, "Forged token is super user"); xdr_free((xdrproc_t)xdr_string, &string); /* Throw away this connection and security class */ rx_DestroyConnection(conn); rxs_Release(class); /* Now fake an rx ticket for a normal user. We have to do more work by hand * here, sadly */ startTime = time(NULL); class = afstest_FakeRxkadClass(dir, "rpctest", "", "", startTime, startTime + 60* 60); conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class, RX_SECIDX_KAD); code = TEST_CanI(conn, &result); is_int(EPERM, code, "Running RPC as non-super user fails as expected"); code = TEST_NewCanI(conn, &result); is_int(EPERM, code, "Running new interface RPC as non-super user fails as expected"); code = TEST_WhoAmI(conn, &string); xdr_free((xdrproc_t)xdr_string, &string); is_int(EPERM, code, "Running RPC returning string fails as expected"); code = TEST_NewWhoAmI(conn, &string); xdr_free((xdrproc_t)xdr_string, &string); is_int(EPERM, code, "Running new interface RPC returning string fails as expected"); ok(afsconf_AddUser(dir, "rpctest") == 0, "Adding %s user works", "rpctest"); code = TEST_CanI(conn, &result); is_int(0, code, "Running RPC as rpctest works"); code = TEST_NewCanI(conn, &result); is_int(0, code, "Running new interface RPC as rpctest works"); code = TEST_WhoAmI(conn, &string); is_int(0, code, "Running RPC returning string as %s works", "rpctest"); is_string("rpctest", string, "Returned user string matches"); xdr_free((xdrproc_t)xdr_string, &string); code = TEST_NewWhoAmI(conn, &string); is_int(0, code, "Running new RPC returning string as %s works", "rpctest"); is_string("rpctest", string, "Returned user string for new interface matches"); xdr_free((xdrproc_t)xdr_string, &string); rx_DestroyConnection(conn); rxs_Release(class); /* Now try with an admin principal */ startTime = time(NULL); class = afstest_FakeRxkadClass(dir, "rpctest", "admin", "", startTime, startTime + 60* 60); conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class, RX_SECIDX_KAD); code = TEST_CanI(conn, &result); is_int(EPERM, code, "Running RPC as non-super user fails as expected"); code = TEST_NewCanI(conn, &result); is_int(EPERM, code, "Running new interface RPC as non-super user fails as expected"); code = TEST_WhoAmI(conn, &string); xdr_free((xdrproc_t)xdr_string, &string); is_int(EPERM, code, "Running RPC returning string fails as expected"); code = TEST_NewWhoAmI(conn, &string); xdr_free((xdrproc_t)xdr_string, &string); is_int(EPERM, code, "Running new interface RPC returning string fails as expected"); ok(afsconf_AddUser(dir, "rpctest.admin") == 0, "Adding %s user works", "rpctest.admin"); code = TEST_CanI(conn, &result); is_int(0, code, "Running RPC as %s works", "rpctest/admin"); code = TEST_NewCanI(conn, &result); is_int(0, code, "Running new interface RPC as %s works", "rpctest/admin"); code = TEST_WhoAmI(conn, &string); is_int(0, code, "Running RPC returning string as %s works", "rpctest/admin"); is_string("rpctest.admin", string, "Returned user string matches"); xdr_free((xdrproc_t)xdr_string, &string); code = TEST_NewWhoAmI(conn, &string); is_int(0, code, "Running new interface RPC returning string as %s works", "rpctest/admin"); is_string("rpctest.admin", string, "Returned user string from new interface matches"); xdr_free((xdrproc_t)xdr_string, &string); rx_DestroyConnection(conn); rxs_Release(class); }
/*! * Copy an identity * * Create a new identity as a copy of an existing one. * * @param from * The identity to copy from * @return * The new identity */ struct rx_identity * rx_identity_copy(struct rx_identity *from) { return rx_identity_new(from->kind, from->displayName, from->exportedName.val, from->exportedName.len); }