Skip to content

Commit b91b5d3

Browse files
committed
Move most of basic_auth handling to a function
Consolidate and simplify AUTH BASIC Handling - Part 3. By moving all the special operation one for auth basic into its own segment we make the code simpler (less exceptions) and more readable. Closes #39 Signed-off-by: Simo Sorce <simo@redhat.com>
1 parent 2970c01 commit b91b5d3

File tree

1 file changed

+160
-126
lines changed

1 file changed

+160
-126
lines changed

src/mod_auth_gssapi.c

Lines changed: 160 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,158 @@ static void mag_set_req_data(request_rec *req,
332332
}
333333
}
334334

335+
static bool mag_auth_basic(request_rec *req,
336+
struct mag_config *cfg,
337+
gss_buffer_desc ba_user,
338+
gss_buffer_desc ba_pwd,
339+
gss_cred_id_t acquired_cred,
340+
gss_cred_usage_t cred_usage,
341+
gss_name_t *client,
342+
gss_OID *mech_type,
343+
gss_cred_id_t *delegated_cred,
344+
uint32_t *vtime)
345+
{
346+
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
347+
const char *user_ccache = NULL;
348+
const char *orig_ccache = NULL;
349+
long long unsigned int rndname;
350+
apr_status_t rs;
351+
#endif
352+
gss_name_t user = GSS_C_NO_NAME;
353+
gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL;
354+
gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT;
355+
gss_name_t server = GSS_C_NO_NAME;
356+
gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
357+
gss_ctx_id_t server_ctx = GSS_C_NO_CONTEXT;
358+
gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
359+
gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
360+
uint32_t init_flags = 0;
361+
uint32_t maj, min;
362+
bool ret = false;
363+
364+
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
365+
rs = apr_generate_random_bytes((unsigned char *)(&rndname),
366+
sizeof(long long unsigned int));
367+
if (rs != APR_SUCCESS) {
368+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
369+
"Failed to generate random ccache name");
370+
goto done;
371+
}
372+
user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname);
373+
maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache);
374+
if (GSS_ERROR(maj)) {
375+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
376+
"In Basic Auth, %s",
377+
mag_error(req, "gss_krb5_ccache_name() "
378+
"failed", maj, min));
379+
goto done;
380+
}
381+
#endif
382+
383+
maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &user);
384+
if (GSS_ERROR(maj)) {
385+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
386+
"In Basic Auth, %s",
387+
mag_error(req, "gss_import_name() failed",
388+
maj, min));
389+
goto done;
390+
}
391+
392+
maj = gss_acquire_cred_with_password(&min, user, &ba_pwd,
393+
GSS_C_INDEFINITE,
394+
cfg->allowed_mechs,
395+
GSS_C_INITIATE,
396+
&user_cred, NULL, NULL);
397+
if (GSS_ERROR(maj)) {
398+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
399+
"In Basic Auth, %s",
400+
mag_error(req, "gss_acquire_cred_with_password() "
401+
"failed", maj, min));
402+
goto done;
403+
}
404+
405+
if (cred_usage == GSS_C_BOTH) {
406+
/* If GSS_C_BOTH is used then inquire_cred will return the client
407+
* name instead of the SPN of the server credentials. Therefore we
408+
* need to acquire a different set of credential setting
409+
* GSS_C_ACCEPT explicitly */
410+
if (!mag_acquire_creds(req, cfg, cfg->allowed_mechs,
411+
GSS_C_ACCEPT, &server_cred, NULL)) {
412+
goto done;
413+
}
414+
} else {
415+
server_cred = acquired_cred;
416+
}
417+
maj = gss_inquire_cred(&min, server_cred, &server,
418+
NULL, NULL, NULL);
419+
if (GSS_ERROR(maj)) {
420+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
421+
"%s", mag_error(req, "gss_inquired_cred_() "
422+
"failed", maj, min));
423+
goto done;
424+
}
425+
426+
#ifdef HAVE_CRED_STORE
427+
if (cfg->deleg_ccache_dir) {
428+
/* delegate ourselves credentials so we store them as requested */
429+
init_flags |= GSS_C_DELEG_FLAG;
430+
}
431+
#endif
432+
433+
do {
434+
/* output and input are inverted here, this is intentional */
435+
maj = gss_init_sec_context(&min, user_cred, &user_ctx, server,
436+
GSS_C_NO_OID, init_flags, 300,
437+
GSS_C_NO_CHANNEL_BINDINGS, &output,
438+
NULL, &input, NULL, NULL);
439+
if (GSS_ERROR(maj)) {
440+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
441+
"%s", mag_error(req, "gss_init_sec_context() "
442+
"failed", maj, min));
443+
goto done;
444+
}
445+
gss_release_buffer(&min, &output);
446+
maj = gss_accept_sec_context(&min, &server_ctx, acquired_cred,
447+
&input, GSS_C_NO_CHANNEL_BINDINGS,
448+
client, mech_type, &output, NULL,
449+
vtime, delegated_cred);
450+
if (GSS_ERROR(maj)) {
451+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
452+
"%s", mag_error(req, "gss_accept_sec_context()"
453+
" failed", maj, min));
454+
goto done;
455+
}
456+
gss_release_buffer(&min, &input);
457+
} while (maj == GSS_S_CONTINUE_NEEDED);
458+
459+
ret = true;
460+
461+
done:
462+
gss_release_buffer(&min, &output);
463+
gss_release_buffer(&min, &input);
464+
gss_release_name(&min, &server);
465+
if (server_cred != acquired_cred) {
466+
gss_release_cred(&min, &server_cred);
467+
}
468+
gss_delete_sec_context(&min, &server_ctx, GSS_C_NO_BUFFER);
469+
gss_release_name(&min, &user);
470+
gss_release_cred(&min, &user_cred);
471+
gss_delete_sec_context(&min, &user_ctx, GSS_C_NO_BUFFER);
472+
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
473+
if (user_ccache != NULL) {
474+
maj = gss_krb5_ccache_name(&min, orig_ccache, NULL);
475+
if (maj != GSS_S_COMPLETE) {
476+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
477+
"Failed to restore per-thread ccache, %s",
478+
mag_error(req, "gss_krb5_ccache_name() "
479+
"failed", maj, min));
480+
}
481+
}
482+
#endif
483+
return ret;
484+
}
485+
486+
335487
static int mag_auth(request_rec *req)
336488
{
337489
const char *type;
@@ -348,12 +500,9 @@ static int mag_auth(request_rec *req)
348500
gss_buffer_desc ba_user;
349501
gss_buffer_desc ba_pwd;
350502
gss_name_t client = GSS_C_NO_NAME;
351-
gss_cred_id_t user_cred = GSS_C_NO_CREDENTIAL;
352503
gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
353-
gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
354504
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
355505
gss_cred_usage_t cred_usage = GSS_C_ACCEPT;
356-
uint32_t flags;
357506
uint32_t vtime;
358507
uint32_t maj, min;
359508
char *reply;
@@ -363,13 +512,6 @@ static int mag_auth(request_rec *req)
363512
gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
364513
gss_buffer_desc lname = GSS_C_EMPTY_BUFFER;
365514
struct mag_conn *mc = NULL;
366-
gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT;
367-
gss_name_t server = GSS_C_NO_NAME;
368-
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
369-
const char *user_ccache = NULL;
370-
const char *orig_ccache = NULL;
371-
#endif
372-
uint32_t init_flags = 0;
373515
time_t expiration;
374516
int i;
375517

@@ -382,6 +524,7 @@ static int mag_auth(request_rec *req)
382524

383525
if (!cfg->allowed_mechs) {
384526
/* Try to fetch the default set if not explicitly configured */
527+
gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL;
385528
(void)mag_acquire_creds(req, cfg, GSS_C_NO_OID_SET, GSS_C_ACCEPT,
386529
&server_cred, &cfg->allowed_mechs);
387530
(void)gss_release_cred(&min, &server_cred);
@@ -543,108 +686,13 @@ static int mag_auth(request_rec *req)
543686
}
544687

545688
if (auth_type == AUTH_TYPE_BASIC) {
546-
maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &client);
547-
if (GSS_ERROR(maj)) {
548-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
549-
"In Basic Auth, %s",
550-
mag_error(req, "gss_import_name() failed",
551-
maj, min));
552-
goto done;
553-
}
554-
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
555-
/* Set a per-thread ccache in case we are using kerberos,
556-
* it is not elegant but avoids interference between threads */
557-
long long unsigned int rndname;
558-
apr_status_t rs;
559-
rs = apr_generate_random_bytes((unsigned char *)(&rndname),
560-
sizeof(long long unsigned int));
561-
if (rs != APR_SUCCESS) {
562-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
563-
"Failed to generate random ccache name");
564-
goto done;
565-
}
566-
user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname);
567-
maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache);
568-
if (GSS_ERROR(maj)) {
569-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
570-
"In Basic Auth, %s",
571-
mag_error(req, "gss_krb5_ccache_name() "
572-
"failed", maj, min));
573-
goto done;
574-
}
575-
#endif
576-
maj = gss_acquire_cred_with_password(&min, client, &ba_pwd,
577-
GSS_C_INDEFINITE,
578-
cfg->allowed_mechs,
579-
GSS_C_INITIATE,
580-
&user_cred, NULL, NULL);
581-
if (GSS_ERROR(maj)) {
582-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
583-
"In Basic Auth, %s",
584-
mag_error(req, "gss_acquire_cred_with_password() "
585-
"failed", maj, min));
586-
goto done;
689+
if (mag_auth_basic(req, cfg, ba_user, ba_pwd,
690+
acquired_cred, cred_usage,
691+
&client, &mech_type,
692+
&delegated_cred, &vtime)) {
693+
goto complete;
587694
}
588-
gss_release_name(&min, &client);
589-
590-
if (cred_usage == GSS_C_BOTH) {
591-
/* If GSS_C_BOTH is used then inquire_cred will return the client
592-
* name instead of the SPN of the server credentials. Therefore we
593-
* need to acquire a different set of credential setting
594-
* GSS_C_ACCEPT explicitly */
595-
if (!mag_acquire_creds(req, cfg, cfg->allowed_mechs,
596-
GSS_C_ACCEPT, &server_cred, NULL)) {
597-
goto done;
598-
}
599-
} else {
600-
server_cred = acquired_cred;
601-
}
602-
maj = gss_inquire_cred(&min, server_cred, &server,
603-
NULL, NULL, NULL);
604-
if (GSS_ERROR(maj)) {
605-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
606-
"%s", mag_error(req, "gss_inquired_cred_() "
607-
"failed", maj, min));
608-
goto done;
609-
}
610-
if (server_cred != acquired_cred) {
611-
gss_release_cred(&min, &server_cred);
612-
}
613-
614-
#ifdef HAVE_CRED_STORE
615-
if (cfg->deleg_ccache_dir) {
616-
/* delegate ourselves credentials so we store them as requested */
617-
init_flags |= GSS_C_DELEG_FLAG;
618-
}
619-
#endif
620-
621-
do {
622-
/* output and input are inverted here, this is intentional */
623-
maj = gss_init_sec_context(&min, user_cred, &user_ctx, server,
624-
GSS_C_NO_OID, init_flags, 300,
625-
GSS_C_NO_CHANNEL_BINDINGS, &output,
626-
NULL, &input, NULL, NULL);
627-
if (GSS_ERROR(maj)) {
628-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
629-
"%s", mag_error(req, "gss_init_sec_context() "
630-
"failed", maj, min));
631-
goto done;
632-
}
633-
gss_release_buffer(&min, &output);
634-
maj = gss_accept_sec_context(&min, pctx, acquired_cred,
635-
&input, GSS_C_NO_CHANNEL_BINDINGS,
636-
&client, &mech_type, &output, &flags,
637-
&vtime, &delegated_cred);
638-
if (GSS_ERROR(maj)) {
639-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
640-
"%s", mag_error(req, "gss_accept_sec_context()"
641-
" failed", maj, min));
642-
goto done;
643-
}
644-
gss_release_buffer(&min, &input);
645-
} while (maj == GSS_S_CONTINUE_NEEDED);
646-
gss_release_buffer(&min, &output);
647-
goto complete;
695+
goto done;
648696
}
649697

650698
if (auth_type == AUTH_TYPE_NEGOTIATE &&
@@ -660,7 +708,7 @@ static int mag_auth(request_rec *req)
660708

661709
maj = gss_accept_sec_context(&min, pctx, acquired_cred,
662710
&input, GSS_C_NO_CHANNEL_BINDINGS,
663-
&client, &mech_type, &output, &flags, &vtime,
711+
&client, &mech_type, &output, NULL, &vtime,
664712
&delegated_cred);
665713
if (GSS_ERROR(maj)) {
666714
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
@@ -771,26 +819,12 @@ static int mag_auth(request_rec *req)
771819
ap_auth_name(req)));
772820
}
773821
}
774-
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
775-
if (user_ccache != NULL) {
776-
maj = gss_krb5_ccache_name(&min, orig_ccache, NULL);
777-
if (maj != GSS_S_COMPLETE) {
778-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
779-
"Failed to restore per-thread ccache, %s",
780-
mag_error(req, "gss_krb5_ccache_name() "
781-
"failed", maj, min));
782-
}
783-
}
784-
#endif
785822
if (ctx != GSS_C_NO_CONTEXT)
786823
gss_delete_sec_context(&min, &ctx, GSS_C_NO_BUFFER);
787-
gss_delete_sec_context(&min, &user_ctx, GSS_C_NO_BUFFER);
788-
gss_release_cred(&min, &user_cred);
789824
gss_release_cred(&min, &acquired_cred);
790825
gss_release_cred(&min, &delegated_cred);
791826
gss_release_buffer(&min, &output);
792827
gss_release_name(&min, &client);
793-
gss_release_name(&min, &server);
794828
gss_release_buffer(&min, &name);
795829
gss_release_buffer(&min, &lname);
796830
return ret;

0 commit comments

Comments
 (0)