You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
8.2 KiB
287 lines
8.2 KiB
diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.old nfs-utils-1.3.0/utils/gssd/gssd_proc.c |
|
--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.old 2015-09-24 09:48:40.833593000 -0400 |
|
+++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c 2015-09-24 09:50:58.747069000 -0400 |
|
@@ -1023,6 +1023,113 @@ change_identity(uid_t uid) |
|
return 0; |
|
} |
|
|
|
+AUTH * |
|
+krb5_not_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname, |
|
+ int *downcall_err, int *chg_err, CLIENT **rpc_clnt) |
|
+{ |
|
+ AUTH *auth = NULL; |
|
+ gss_cred_id_t gss_cred; |
|
+ char **dname; |
|
+ int err, resp = -1; |
|
+ |
|
+ printerr(1, "krb5_not_machine_creds: uid %d tgtname %s\n", |
|
+ uid, tgtname); |
|
+ |
|
+ *chg_err = change_identity(uid); |
|
+ if (*chg_err) { |
|
+ printerr(0, "WARNING: failed to change identity: %s", |
|
+ strerror(*chg_err)); |
|
+ goto out; |
|
+ } |
|
+ |
|
+ /** Tell krb5 gss which credentials cache to use. |
|
+ * Try first to acquire credentials directly via GSSAPI |
|
+ */ |
|
+ err = gssd_acquire_user_cred(&gss_cred); |
|
+ if (err == 0) |
|
+ resp = create_auth_rpc_client(clp, tgtname, rpc_clnt, |
|
+ &auth, uid, |
|
+ AUTHTYPE_KRB5, gss_cred); |
|
+ |
|
+ /** if create_auth_rplc_client fails try the traditional |
|
+ * method of trolling for credentials |
|
+ */ |
|
+ for (dname = ccachesearch; resp != 0 && *dname != NULL; dname++) { |
|
+ err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, |
|
+ *dname); |
|
+ if (err == -EKEYEXPIRED) |
|
+ *downcall_err = -EKEYEXPIRED; |
|
+ else if (err == 0) |
|
+ resp = create_auth_rpc_client(clp, tgtname, rpc_clnt, |
|
+ &auth, uid,AUTHTYPE_KRB5, |
|
+ GSS_C_NO_CREDENTIAL); |
|
+ } |
|
+ |
|
+out: |
|
+ return auth; |
|
+} |
|
+ |
|
+AUTH * |
|
+krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname, |
|
+ char *service, CLIENT **rpc_clnt) |
|
+{ |
|
+ AUTH *auth = NULL; |
|
+ char **credlist = NULL; |
|
+ char **ccname; |
|
+ int nocache = 0; |
|
+ int success = 0; |
|
+ |
|
+ printerr(1, "krb5_use_machine_creds: uid %d tgtname %s\n", |
|
+ uid, tgtname); |
|
+ |
|
+ do { |
|
+ gssd_refresh_krb5_machine_credential(clp->servername, NULL, |
|
+ service); |
|
+ /* |
|
+ * Get a list of credential cache names and try each |
|
+ * of them until one works or we've tried them all |
|
+ */ |
|
+ if (gssd_get_krb5_machine_cred_list(&credlist)) { |
|
+ printerr(0, "ERROR: No credentials found " |
|
+ "for connection to server %s\n", |
|
+ clp->servername); |
|
+ goto out; |
|
+ } |
|
+ for (ccname = credlist; ccname && *ccname; ccname++) { |
|
+ gssd_setup_krb5_machine_gss_ccache(*ccname); |
|
+ if ((create_auth_rpc_client(clp, tgtname, rpc_clnt, |
|
+ &auth, uid, |
|
+ AUTHTYPE_KRB5, |
|
+ GSS_C_NO_CREDENTIAL)) == 0) { |
|
+ /* Success! */ |
|
+ success++; |
|
+ break; |
|
+ } |
|
+ printerr(2, "WARNING: Failed to create machine krb5" |
|
+ "context with cred cache %s for server %s\n", |
|
+ *ccname, clp->servername); |
|
+ } |
|
+ gssd_free_krb5_machine_cred_list(credlist); |
|
+ if (!success) { |
|
+ if(nocache == 0) { |
|
+ nocache++; |
|
+ printerr(2, "WARNING: Machine cache prematurely" "expired or corrupted trying to" |
|
+ "recreate cache for server %s\n", |
|
+ clp->servername); |
|
+ } else { |
|
+ printerr(1, "WARNING: Failed to create machine" |
|
+ "krb5 context with any credentials" |
|
+ "cache for server %s\n", |
|
+ clp->servername); |
|
+ goto out; |
|
+ } |
|
+ } |
|
+ } while(!success); |
|
+ |
|
+out: |
|
+ return auth; |
|
+} |
|
+ |
|
/* |
|
* this code uses the userland rpcsec gss library to create a krb5 |
|
* context on behalf of the kernel |
|
@@ -1035,40 +1142,13 @@ process_krb5_upcall(struct clnt_info *cl |
|
AUTH *auth = NULL; |
|
struct authgss_private_data pd; |
|
gss_buffer_desc token; |
|
- char **credlist = NULL; |
|
- char **ccname; |
|
- char **dirname; |
|
- int create_resp = -1; |
|
int err, downcall_err = -EACCES; |
|
- gss_cred_id_t gss_cred; |
|
OM_uint32 maj_stat, min_stat, lifetime_rec; |
|
- pid_t pid; |
|
+ pid_t pid, childpid = -1; |
|
gss_name_t gacceptor = GSS_C_NO_NAME; |
|
gss_OID mech; |
|
gss_buffer_desc acceptor = {0}; |
|
|
|
- pid = fork(); |
|
- switch(pid) { |
|
- case 0: |
|
- /* Child: fall through to rest of function */ |
|
- break; |
|
- case -1: |
|
- /* fork() failed! */ |
|
- printerr(0, "WARNING: unable to fork() to handle upcall: %s\n", |
|
- strerror(errno)); |
|
- return; |
|
- default: |
|
- /* Parent: just wait on child to exit and return */ |
|
- do { |
|
- pid = wait(&err); |
|
- } while(pid == -1 && errno != -ECHILD); |
|
- |
|
- if (WIFSIGNALED(err)) |
|
- printerr(0, "WARNING: forked child was killed with signal %d\n", |
|
- WTERMSIG(err)); |
|
- return; |
|
- } |
|
- |
|
printerr(1, "handling krb5 upcall (%s)\n", clp->dirname); |
|
|
|
token.length = 0; |
|
@@ -1101,76 +1181,48 @@ process_krb5_upcall(struct clnt_info *cl |
|
if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 && |
|
service == NULL)) { |
|
|
|
- err = change_identity(uid); |
|
- if (err) { |
|
- printerr(0, "WARNING: failed to change identity: %s", |
|
- strerror(err)); |
|
- goto out_return_error; |
|
- } |
|
+ /* already running as uid 0 */ |
|
+ if (uid == 0) |
|
+ goto no_fork; |
|
+ |
|
+ pid = fork(); |
|
+ switch(pid) { |
|
+ case 0: |
|
+ /* Child: fall through to rest of function */ |
|
+ childpid = getpid(); |
|
+ unsetenv("KRB5CCNAME"); |
|
+ printerr(1, "CHILD forked pid %d \n", childpid); |
|
+ break; |
|
+ case -1: |
|
+ /* fork() failed! */ |
|
+ printerr(0, "WARNING: unable to fork() to handle" |
|
+ "upcall: %s\n", strerror(errno)); |
|
+ return; |
|
+ default: |
|
+ /* Parent: just wait on child to exit and return */ |
|
+ do { |
|
+ pid = wait(&err); |
|
+ } while(pid == -1 && errno != -ECHILD); |
|
|
|
- /* Tell krb5 gss which credentials cache to use */ |
|
- /* Try first to acquire credentials directly via GSSAPI */ |
|
- err = gssd_acquire_user_cred(&gss_cred); |
|
- if (!err) |
|
- create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid, |
|
- AUTHTYPE_KRB5, gss_cred); |
|
- /* if create_auth_rplc_client fails try the traditional method of |
|
- * trolling for credentials */ |
|
- for (dirname = ccachesearch; create_resp != 0 && *dirname != NULL; dirname++) { |
|
- err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname); |
|
- if (err == -EKEYEXPIRED) |
|
- downcall_err = -EKEYEXPIRED; |
|
- else if (!err) |
|
- create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid, |
|
- AUTHTYPE_KRB5, GSS_C_NO_CREDENTIAL); |
|
+ if (WIFSIGNALED(err)) |
|
+ printerr(0, "WARNING: forked child was killed" |
|
+ "with signal %d\n", WTERMSIG(err)); |
|
+ return; |
|
} |
|
+no_fork: |
|
+ |
|
+ auth = krb5_not_machine_creds(clp, uid, tgtname, &downcall_err, |
|
+ &err, &rpc_clnt); |
|
+ if (err) |
|
+ goto out_return_error; |
|
} |
|
- if (create_resp != 0) { |
|
+ if (auth == NULL) { |
|
if (uid == 0 && (root_uses_machine_creds == 1 || |
|
service != NULL)) { |
|
- int nocache = 0; |
|
- int success = 0; |
|
- do { |
|
- gssd_refresh_krb5_machine_credential(clp->servername, |
|
- NULL, service); |
|
- /* |
|
- * Get a list of credential cache names and try each |
|
- * of them until one works or we've tried them all |
|
- */ |
|
- if (gssd_get_krb5_machine_cred_list(&credlist)) { |
|
- printerr(0, "ERROR: No credentials found " |
|
- "for connection to server %s\n", |
|
- clp->servername); |
|
- goto out_return_error; |
|
- } |
|
- for (ccname = credlist; ccname && *ccname; ccname++) { |
|
- gssd_setup_krb5_machine_gss_ccache(*ccname); |
|
- if ((create_auth_rpc_client(clp, tgtname, &rpc_clnt, |
|
- &auth, uid, |
|
- AUTHTYPE_KRB5, |
|
- GSS_C_NO_CREDENTIAL)) == 0) { |
|
- /* Success! */ |
|
- success++; |
|
- break; |
|
- } |
|
- printerr(2, "WARNING: Failed to create machine krb5 context " |
|
- "with credentials cache %s for server %s\n", |
|
- *ccname, clp->servername); |
|
- } |
|
- gssd_free_krb5_machine_cred_list(credlist); |
|
- if (!success) { |
|
- if(nocache == 0) { |
|
- nocache++; |
|
- printerr(2, "WARNING: Machine cache is prematurely expired or corrupted " |
|
- "trying to recreate cache for server %s\n", clp->servername); |
|
- } else { |
|
- printerr(1, "WARNING: Failed to create machine krb5 context " |
|
- "with any credentials cache for server %s\n", |
|
- clp->servername); |
|
- goto out_return_error; |
|
- } |
|
- } |
|
- } while(!success); |
|
+ auth = krb5_use_machine_creds(clp, uid, tgtname, |
|
+ service, &rpc_clnt); |
|
+ if (auth == NULL) |
|
+ goto out_return_error; |
|
} else { |
|
printerr(1, "WARNING: Failed to create krb5 context " |
|
"for user with uid %d for server %s\n", |
|
@@ -1225,7 +1277,12 @@ out: |
|
AUTH_DESTROY(auth); |
|
if (rpc_clnt) |
|
clnt_destroy(rpc_clnt); |
|
- exit(0); |
|
+ |
|
+ pid = getpid(); |
|
+ if (pid == childpid) |
|
+ exit(0); |
|
+ else |
|
+ return; |
|
|
|
out_return_error: |
|
do_error_downcall(fd, uid, downcall_err);
|
|
|