#include <osilog.h>
#include <rxkad_prototypes.h> /* for life_to_time */
+#include <afs/ptserver.h>
/*
* TIMING _____________________________________________________________________
#endif /* USE_MS2MIT */
/* Static Prototypes */
-char *afs_realm_of_cell(struct afsconf_cell *);
+char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
+int
+KFW_use_krb524(void)
+{
+ HKEY parmKey;
+ DWORD code, len;
+ DWORD use524 = 0;
+
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(use524);
+ code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+ (BYTE *) &use524, &len);
+ if (code != ERROR_SUCCESS) {
+ RegCloseKey(parmKey);
+
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(use524);
+ code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+ (BYTE *) &use524, &len);
+ if (code != ERROR_SUCCESS)
+ use524 = 0;
+ }
+ }
+ RegCloseKey (parmKey);
+ }
+ return use524;
+}
+
int
KFW_is_available(void)
{
HKEY parmKey;
- DWORD code, len;
+ DWORD code, len;
DWORD enableKFW = 1;
code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
0, KEY_QUERY_VALUE, &parmKey);
- if (code != ERROR_SUCCESS)
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
- if (code == ERROR_SUCCESS) {
+ if (code == ERROR_SUCCESS) {
len = sizeof(enableKFW);
code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
(BYTE *) &enableKFW, &len);
if (code != ERROR_SUCCESS) {
- enableKFW = 1;
+ RegCloseKey(parmKey);
+
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(enableKFW);
+ code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
+ (BYTE *) &enableKFW, &len);
+ if (code != ERROR_SUCCESS)
+ enableKFW = 1;
+ }
}
RegCloseKey (parmKey);
- }
-
+ }
if ( !enableKFW )
return FALSE;
krb5_ccache cc = 0;
krb5_principal princ = 0;
char * pname = NULL;
- krb5_data * realm;
+ krb5_data * princ_realm;
krb5_error_code code;
- char cell[128]="";
+ char cell[128]="", realm[128]="";
int i;
if (!pkrb5_init_context)
code = pkrb5_unparse_name(ctx,princ,&pname);
if ( code ) goto cleanup;
- realm = krb5_princ_realm(ctx, princ);
- for ( i=0; i<realm->length; i++ ) {
- cell[i] = tolower(realm->data[i]);
+ princ_realm = krb5_princ_realm(ctx, princ);
+ for ( i=0; i<princ_realm->length; i++ ) {
+ realm[i] = princ_realm->data[i];
+ cell[i] = tolower(princ_realm->data[i]);
}
- cell[i] = '\0';
+ cell[i] = '\0';
+ realm[i] = '\0';
- code = KFW_AFS_klog(ctx, cc, "afs", cell, realm->data, pLeash_get_default_lifetime(),NULL);
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
int
-KFW_AFS_get_cred(char * username,
+KFW_AFS_get_cred( char * username,
char * cell,
char * password,
int lifetime,
char **cells = NULL;
int cell_count=0;
struct afsconf_cell cellconfig;
+ char * dot;
+
if (!pkrb5_init_context)
return 0;
if ( code ) goto cleanup;
realm = strchr(username,'@');
- if (realm) {
+ if ( realm ) {
+ pname = strdup(username);
+ realm = strchr(pname, '@');
*realm = '\0';
- realm++;
+
+ /* handle kerberos iv notation */
+ while ( dot = strchr(pname,'.') ) {
+ *dot = '/';
+ }
+ *realm++ = '@';
+ } else {
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
+ pname = malloc(strlen(username) + strlen(realm) + 2);
+
+ strcpy(pname, username);
+
+ /* handle kerberos iv notation */
+ while ( dot = strchr(pname,'.') ) {
+ *dot = '/';
+ }
+
+ strcat(pname,"@");
+ strcat(pname,realm);
}
- if ( !realm || !realm[0] )
- realm = afs_realm_of_cell(&cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString("\n");
}
- code = pkrb5_build_principal(ctx, &principal, strlen(realm),
- realm, username,
- NULL,
- NULL);
-
- code = KFW_get_ccache(ctx, principal, &cc);
+ code = pkrb5_parse_name(ctx, pname, &principal);
if ( code ) goto cleanup;
- code = pkrb5_unparse_name(ctx, principal, &pname);
+ code = KFW_get_ccache(ctx, principal, &cc);
if ( code ) goto cleanup;
if ( lifetime == 0 )
lifetime = pLeash_get_default_lifetime();
- code = KFW_kinit(ctx, cc, HWND_DESKTOP,
- pname,
- password,
- lifetime,
- pLeash_get_default_forwardable(),
- pLeash_get_default_proxiable(),
- pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
- pLeash_get_default_noaddresses(),
- pLeash_get_default_publicip());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_kinit() returns: %d\n",code);
- OutputDebugString(message);
+ if ( password && password[0] ) {
+ code = KFW_kinit( ctx, cc, HWND_DESKTOP,
+ pname,
+ password,
+ lifetime,
+ pLeash_get_default_forwardable(),
+ pLeash_get_default_proxiable(),
+ pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
+ pLeash_get_default_noaddresses(),
+ pLeash_get_default_publicip());
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_kinit() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ if ( code ) goto cleanup;
+
+ KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
}
- if ( code ) goto cleanup;
-
- KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
if ( IsDebuggerPresent() ) {
code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
if ( code ) continue;
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
cleanup:
if ( pname )
- pkrb5_free_unparsed_name(ctx,pname);
+ free(pname);
if ( cc )
pkrb5_cc_close(ctx, cc);
}
code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
if ( code ) continue;
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
if ( code ) goto loop_cleanup;
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
return(0);
}
+
+#define ALLOW_REGISTER 1
+static int
+ViceIDToUsername(char *username,
+ char *realm_of_user,
+ char *realm_of_cell,
+ char * cell_to_use,
+ 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];
+ long viceId; /* AFS uid of user */
+ int status = 0;
+#ifdef ALLOW_REGISTER
+ afs_int32 id;
+#endif /* ALLOW_REGISTER */
+
+ if (confname[0] == '\0') {
+ strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
+ confname[sizeof(confname) - 2] = '\0';
+ }
+
+ /*
+ * Talk about DUMB! It turns out that there is a bug in
+ * pr_Initialize -- even if you give a different cell name
+ * to it, it still uses a connection to a previous AFS server
+ * if one exists. The way to fix this is to change the
+ * _filename_ argument to pr_Initialize - that forces it to
+ * re-initialize the connection. We do this by adding and
+ * removing a "/" on the end of the configuration directory name.
+ */
+
+ if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
+ int i = strlen(confname);
+ if (confname[i - 1] == '/') {
+ confname[i - 1] = '\0';
+ } else {
+ confname[i] = '/';
+ confname[i + 1] = '\0';
+ }
+ }
+
+ strcpy(lastcell, aserver->cell);
+
+ if (!pr_Initialize (0, confname, aserver->cell))
+ status = pr_SNameToId (username, &viceId);
+
+ /*
+ * 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.
+ */
+
+ /*
+ * 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) {
+ id = 0;
+ strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
+ strcpy(aclient->instance, "");
+ strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
+ if (status = ktc_SetToken(aserver, atoken, aclient, 0))
+ return status;
+
+ /*
+ * 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, 0))
+ return status;
+ if (status = pr_CreateUser(username, &id))
+ return status;
+#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 */
+ }
+ }
+#endif /* ALLOW_REGISTER */
+ return status;
+}
+
+
int
KFW_AFS_klog(
krb5_context alt_ctx,
memset(ServiceName, '\0', sizeof(ServiceName));
memset(realm_of_user, '\0', sizeof(realm_of_user));
memset(realm_of_cell, '\0', sizeof(realm_of_cell));
- if (cell && cell[0])
- strcpy(Dmycell, cell);
- else
- memset(Dmycell, '\0', sizeof(Dmycell));
+ if (cell && cell[0])
+ strcpy(Dmycell, cell);
+ else
+ memset(Dmycell, '\0', sizeof(Dmycell));
// NULL or empty cell returns information on local cell
if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
memset((char *)&increds, 0, sizeof(increds));
code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
- if (code) {
+ if (code) {
if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
{
OutputDebugString("Principal Not Found for ccache\n");
}
goto skip_krb5_init;
}
+
+ if ( strchr(krb5_princ_component(ctx,client_principal,0),'.') != NULL )
+ {
+ OutputDebugString("Illegal Principal name contains dot in first component\n");
+ rc = KRB5KRB_ERR_GENERIC;
+ goto cleanup;
+ }
+
i = krb5_princ_realm(ctx, client_principal)->length;
if (i > REALM_SZ-1)
i = REALM_SZ-1;
#else
goto cleanup;
#endif
- strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
+ strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
if (strlen(service) == 0)
strcpy(ServiceName, "afs");
* No need to perform a krb524 translation which is
* commented out in the code below
*/
- if (k5creds->ticket.length > MAXKTCTICKETLEN)
+ if (KFW_use_krb524() ||
+ k5creds->ticket.length > MAXKTCTICKETLEN)
goto try_krb524d;
memset(&aserver, '\0', sizeof(aserver));
p[len] = '\0';
}
+ ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
+ &aclient, &aserver, &atoken);
+
if ( smbname ) {
- strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
- aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+ strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+ aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
} else {
aclient.smbname[0] = '\0';
}
- rc = ktc_SetToken(&aserver, &atoken, &aclient, 0);
+ rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
if (!rc)
goto cleanup; /* We have successfully inserted the token */
strcpy(aclient.cell, CellName);
+ ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
+ &aclient, &aserver, &atoken);
+
if ( smbname ) {
- strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
- aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+ strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+ aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
} else {
aclient.smbname[0] = '\0';
}
- if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0))
+ if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
{
KFW_AFS_error(rc, "ktc_SetToken()");
code = rc;
/* afs_realm_of_cell(): */
/**************************************/
static char *
-afs_realm_of_cell(struct afsconf_cell *cellconfig)
+afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
{
static char krbrlm[REALM_SZ+1]="";
- krb5_context ctx = 0;
char ** realmlist=NULL;
krb5_error_code r;
if (!cellconfig)
return 0;
- if (!pkrb5_init_context)
- return 0;
-
- r = pkrb5_init_context(&ctx);
- if ( !r )
- r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
+ r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
if ( !r && realmlist && realmlist[0] ) {
strcpy(krbrlm, realmlist[0]);
pkrb5_free_host_realm(ctx, realmlist);
}
- if (ctx)
- pkrb5_free_context(ctx);
if ( !krbrlm[0] )
{
char password[PROBE_PASSWORD_LEN+1];
BOOL serverReachable = 0;
- realm = afs_realm_of_cell(cellconfig); // do not free
+ if (!pkrb5_init_context)
+ return 0;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+
+ realm = afs_realm_of_cell(ctx, cellconfig); // do not free
code = pkrb5_build_principal(ctx, &principal, strlen(realm),
realm, PROBE_USERNAME, NULL, NULL);