#include <afs/dirpath.h>
#include <rx/rxkad.h>
#include <afs/auth.h>
+#include <afs/ktc.h>
+#include <afs/token.h>
#include <afs/ptserver.h>
#include "aix_auth_prototypes.h"
+static int uidpag = 0;
+static int localuid = 0;
struct afsconf_cell ak_cellconfig; /* General information about the cell */
static char linkedcell[MAXCELLCHARS+1];
static krb5_ccache _krb425_ccache = NULL;
#error "Must have either keyblock or session member of krb5_creds"
#endif
-char *afs_realm_of_cell(krb5_context context, struct afsconf_cell *cellconfig, int fallback)
+char *
+afs_realm_of_cell(krb5_context context, struct afsconf_cell *cellconfig, int fallback)
{
static char krbrlm[REALM_SZ+1];
char **hrealms = 0;
int status;
krb5_context context;
+ syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: uidpag %s localuid %s",
+ uidpag ? "yes" : "no",
+ localuid ? "yes" : "no");
+
krb5_init_context(&context);
*reenter = 0;
*message = (char *)0;
return AUTH_SUCCESS;
}
-static krb5_error_code get_credv5(krb5_context context, char *user,
- char *name, char *inst, char *realm,
- krb5_creds **creds)
+static krb5_error_code
+get_credv5(krb5_context context, char *user,
+ char *name, char *inst, char *realm,
+ krb5_creds **creds)
{
krb5_creds increds;
krb5_error_code r;
}
-static int get_user_realm(krb5_context context, char *realm)
+static int
+get_user_realm(krb5_context context, char *realm)
{
static krb5_principal client_principal = 0;
int i;
return NULL;
}
+static void *
+aklog_open(char *name, char *domain, int mode, char *options)
+{
+ char *opt;
+
+ /* I can't find this documented anywhere, but it looks like the "options"
+ * string is NUL-delimited (so NULs replace commas in the configuration
+ * file), and the end of the list is marked by an extra NUL. */
+
+ for (opt = options; opt && *opt; opt += strlen(opt) + 1) {
+ if (strcasecmp(opt, "uidpag") == 0) {
+ uidpag = 1;
+ }
+ if (strcasecmp(opt, "localuid") == 0) {
+ localuid = 1;
+ }
+ }
+ return NULL;
+}
-static int get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell, char *linkedcell)
+static int
+get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell, char *linkedcell)
{
int status = 0;
struct afsconf_dir *configdir;
* doing anything. Otherwise, log to it and mark that it has been logged
* to.
*/
-static int auth_to_cell(krb5_context context, char *user, char *cell, char *realm)
+static int
+auth_to_cell(krb5_context context, char *user, char *cell, char *realm)
{
int status = 0;
char username[BUFSIZ]; /* To hold client username structure */
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 */
- static char lastcell[MAXCELLCHARS+1] = { 0 };
static char confname[512] = { 0 };
krb5_creds *v5cred = NULL;
struct ktc_principal aserver;
- struct ktc_principal aclient;
- struct ktc_token atoken, btoken;
int afssetpag = 0, uid = -1;
- struct passwd *pwd;
+ struct passwd *pwd = NULL;
+ struct ktc_setTokenData *token = NULL;
+ struct ktc_tokenUnion *rxkadToken = NULL;
memset(name, 0, sizeof(name));
memset(primary_instance, 0, sizeof(primary_instance));
secondary_instance[sizeof(secondary_instance)-1] = '\0';
}
+ token = token_buildTokenJar(ak_cellconfig.name);
+ if (!token) {
+ syslog(LOG_AUTH|LOG_ERR, "LAM aklog: token_buildTokenJar returns NULL");
+ return ENOMEM;
+ }
+
/*
* Extract the session key from the ticket file and hand-frob an
* afs style authenticator.
if (!afs_realm) {
syslog(LOG_AUTH|LOG_ERR, "LAM aklog: afs_realm_of_cell returns %d", status);
- return AFSCONF_FAILURE;
+ status = AFSCONF_FAILURE;
+ goto done;
}
strcpy(realm_of_cell, afs_realm);
if (status) {
syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_credv5 returns %d", status);
- return status;
+ goto done;
}
strncpy(aserver.name, AFSKEY, MAXKTCNAMELEN - 1);
{
char *p;
int len;
+ struct ktc_token atoken;
len = min(get_princ_len(context, v5cred->client, 0),
second_comp(context, v5cred->client) ?
get_cred_keylen(v5cred));
atoken.ticketLen = v5cred->ticket.length;
memcpy(atoken.ticket, v5cred->ticket.data, atoken.ticketLen);
+
+ status = token_importRxkadViceId(&rxkadToken, &atoken, 0);
+ if (status) {
+ syslog(LOG_AUTH|LOG_ERR, "LAM aklog: importRxkad failed with %d", status);
+ goto done;
+ }
+ }
+
+ status = token_addToken(token, rxkadToken);
+ if (status) {
+ syslog(LOG_AUTH|LOG_ERR, "LAM aklog: addToken failed with %d", status);
+ goto done;
}
if ((status = get_user_realm(context, realm_of_user))) {
syslog(LOG_AUTH|LOG_ERR, "LAM aklog: get_user_realm returns %d", status);
- return KRB5_REALM_UNKNOWN;
+ status = KRB5_REALM_UNKNOWN;
+ goto done;
}
if (strcmp(realm_of_user, realm_of_cell)) {
strcat(username, "@");
strcat(username, realm_of_user);
}
- strcpy(lastcell, aserver.cell);
+ uid = getuid();
+ if (uid == 0) {
+ pwd = getpwnam(user);
+ if (!pwd) {
+ syslog(LOG_AUTH|LOG_ERR, "LAM aklog: getpwnam %s failed", user);
+ status = AUTH_FAILURE;
+ goto done;
+ }
+ }
- /*
- * This is a crock, but it is Transarc's crock, so
- * we have to play along in order to get the
- * functionality. The way the afs id is stored is
- * as a string in the username field of the token.
- * Contrary to what you may think by looking at
- * the code for tokens, this hack (AFS ID %d) will
- * not work if you change %d to something else.
- */
+ viceId = ANONYMOUSID;
-#if 0
- /* This actually crashes long-running daemons */
- if (!pr_Initialize (0, confname, aserver.cell))
- status = pr_SNameToId (username, &viceId);
- if ((status == 0) && (viceId != ANONYMOUSID))
- sprintf (username, "AFS ID %d", (int) viceId);
-#else
- /*
- * This actually only works assuming that your uid and pts space match
- * and probably this works only for the local cell anyway.
- */
+ if (!localuid) {
+ /* This actually crashes long-running daemons */
+ if (!pr_Initialize (0, confname, aserver.cell))
+ status = pr_SNameToId (username, &viceId);
+ if (status)
+ viceId = ANONYMOUSID;
+ } else {
+ /*
+ * This actually only works assuming that your uid and pts space match
+ * and probably this works only for the local cell anyway.
+ */
- if ((uid = getuid()) == 0) {
- if ((pwd = getpwnam(user)) == NULL) {
- syslog(LOG_AUTH|LOG_ERR, "LAM aklog: getpwnam %s failed", user);
- return AUTH_FAILURE;
+ if (uid == 0) {
+ viceId = pwd->pw_uid;
+ } else {
+ viceId = uid;
}
}
/* Don't do first-time registration. Handle only the simple case */
- if ((status == 0) && (viceId != ANONYMOUSID))
- sprintf (username, "AFS ID %d", ((uid==0)?(int)pwd->pw_uid:(int)uid));
-#endif
-
- /* 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, "");
- strncpy(aclient.cell, realm_of_user, MAXKTCREALMLEN - 1);
+ if ((status == 0) && (viceId != ANONYMOUSID)) {
+ status = token_setRxkadViceId(rxkadToken, viceId);
+ if (status) {
+ syslog(LOG_AUTH|LOG_ERR, "LAM aklog: Error %d setting rxkad ViceId", status);
+ status = 0;
+ } else {
+ token_replaceToken(token, &rxkadToken);
+ syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: setting tokens for ViceId %d\n",
+ (int)viceId);
+ }
+ }
#ifndef AFS_AIX51_ENV
/* on AIX 4.1.4 with AFS 3.4a+ if a write is not done before
*/
write(2,"",0); /* dummy write */
#endif
- afssetpag = (getpagvalue("afs") > 0) ? 1 : 0;
- if (uid == 0) {
+
+ /* If uidpag is set, we want to use UID-based PAGs, and not real PAGs, so
+ * don't create a new PAG if we're not in a PAG. But if uidpag is _not_
+ * set, just always create a new PAG. */
+ if (uidpag) {
+ afssetpag = (getpagvalue("afs") > 0) ? 1 : 0;
+ if (afssetpag) {
+ /* we can't set a UID PAG if we're already in a real PAG. Whine */
+ syslog(LOG_AUTH|LOG_ERR, "LAM aklog: uidpag is set, but we are "
+ "already in a PAG; this cannot work! "
+ "Attempting to continue by creating a "
+ "a new PAG");
+ }
+ } else {
+ afssetpag = 1;
+ }
+ token_setPag(token, afssetpag);
+
+ if (uid == 0 && uidpag) {
+ /* We are root, and we want to use UID-based PAGs. So, fork a child
+ * and setuid before setting tokens, so we set the tokens for the
+ * target user. */
struct sigaction newAction, origAction;
pid_t cid, pcid;
int wstatus;
status = sigaction(SIGCHLD, &newAction, &origAction);
if (status) {
syslog(LOG_AUTH|LOG_ERR, "LAM aklog: sigaction returned %d", status);
- return AUTH_FAILURE;
+ status = AUTH_FAILURE;
+ goto done;
}
syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: in daemon? forking to set tokens");
cid = fork();
if (cid <= 0) {
syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog child: setting tokens");
setuid(pwd->pw_uid);
- status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag);
+ status = ktc_SetTokenEx(token);
if (status != 0)
syslog(LOG_AUTH|LOG_ERR, "LAM aklog child: set tokens, returning %d", status);
exit((status == 0)?0:255);
syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: collected child status %d", status);
sigaction(SIGCHLD, &origAction, NULL);
} else {
- status = ktc_SetToken(&aserver, &atoken, &aclient, afssetpag);
+ status = ktc_SetTokenEx(token);
}
if (status != 0)
syslog(LOG_AUTH|LOG_ERR, "LAM aklog: set tokens returned %d", status);
else
syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog: set tokens, pag %d", getpagvalue("afs"));
+
+ done:
+ if (rxkadToken) {
+ token_freeImportedToken(&rxkadToken);
+ }
+ token_FreeSet(&token);
return(status);
}
syslog(LOG_AUTH|LOG_DEBUG, "LAM aklog loaded: uid %d pag %d", getuid(), getpagvalue("afs"));
/*
* Initialize the exported interface routines.
- * Aside from method_authenticate, these are just no-ops.
+ * Aside from method_authenticate and method_open, these are just no-ops.
*/
meths->method_chpass = aklog_chpass;
meths->method_authenticate = aklog_authenticate;
meths->method_passwdexpired = aklog_passwdexpired;
meths->method_passwdrestrictions = aklog_passwdrestrictions;
meths->method_getpasswd = aklog_getpasswd;
+ meths->method_open = aklog_open;
return (0);
}