Package: webauth Version: 3.5.5-1 XX-Debbugs-CC: [EMAIL PROTECTED] XX-Debbugs-CC: [EMAIL PROTECTED] Severity: wishlist Tags: patch
Hello everybody, Russ, as discussed in https://mailman.stanford.edu/pipermail/webauth-info/2007-June/000286.html here it finally is: a patch that allows Weblogin to use forwarded credentials instead of a username and password. (Well, I must admit, that were some very long three weeks ;-) The difference to remote user authentication is that Webauth does not trust the web-server about the username and then create pseudo tokens. With ticket forwarding to the Weblogin URL in effect, webauth can validate the transfered TGT and hence strongly authenticate the user itself. With a TGT available it can also provide Kerberos Tokens, just as it were with password authentication. However, we've added one restriction: if a WAS requires password authentication, the WebKDC won't use the forwarded credentials. How it works: Weblogin (login.fcgi) has been adjusted to check if forwarded Kerberos Tickets are available. If so, the script will store the delegated TGT in the login token instead of a username and password (and the user won't be bothered with the login page) For this purpose the login token format has been enhanced to hold either a username and password or a credential-type declaration of "krb5" and an encoded Kerberos TGT. The WebKDC has been modified so that it accepts a username and a password (as usual, mk_do_login) as well as a TGT (new, mk_do_auto_login_krb5). However, "did_login" will only be set with successful password authentication. This is useful for applications that require the user to login with username and password. To enable mk_do_auto_login_krb5 to verify the supplied TGT, the private function verify_tgt in krb5.c has been exported to the webauth api as webauth_krb5_verify_tgt. Resulting behaviour: With Remote-User support enabled in Webauth and Credential-Delegation enabled in the user's web-browser for the weblogin URL, the user can login without supplying a password. In contrast to Remote-User, the client will be able to access any WAS that needs Kerberos credentials. For any WAS that does not require password authentication, we skip the confirmation page if the user has been authenticated with a forwarded TGT. This is to give our users a real single sign-on feeling. Closing the Browser won't be too useful anyway - the page is accessible immediately again with the credentials cached in the ticket cache of the operating system --- unless the users have destroyed their ticket caches manually. That's about it :-) Regards, Joachim Keltsch and Thomas Götz
diff -ru webauth-3.5.5.orig/doc/install-spnego webauth-3.5.5/doc/install-spnego --- webauth-3.5.5.orig/doc/install-spnego 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/doc/install-spnego 2008-02-19 22:16:10.000000000 +0100 @@ -85,6 +85,15 @@ will bypass the login prompt. If it does need additional information, the user will get the login screen anyway. + If the Browser also supports ticket forwarding and is configured to + do so for the Weblogin URL, a TGT is forwarded to the Weblogin script. + The script will then pass the TGT to the WebKDC instead of a username + and password. The WebKDC in turn will then be able to supply Kerberos + authenticators to remote systems that have requested any. + With ticket forwarding in effect, the user will get the login screen + only if the remote system explicitly requires password authentication. + Note that the lifetime of the TGT will be used instead of $REMUSER_EXPIRES. + If the SPNEGO authentication fails, /login-simple will be run as the error handler. It understands how to extract the WebAuth information out of the environment and present the regular login page. The user's @@ -109,16 +118,23 @@ adding a way to export the expiration time of the ticket from mod_auth_kerb to somewhere the Weblogin script can see it. + If the browser has not only authenticated using SPNEGO but has also + forwarded a TGT to the Weblogin script, the missing piece of information + is available: Weblogin then uses the expiration time of the TGT (after + having validated the TGT). + Besides, the Weblogin server will then set a single sign-on cookie exactly + the way it normally does with password authentication. + Implementation Details Under the hood, if the Weblogin script sees $HONOR_REMOTE_USER is set - and finds REMOTE_USER in the environment, what it does is create a - webkdc-proxy token using the WebKDC keyring, with a proxy subject of - "WEBKDC:remuser". It then passes that webkdc-proxy token in to the - WebKDC in an initial request and sees if it gets back the desired tokens - based on the strength of that webkdc-proxy token. If it does, it - proceeds to the confirmation screen; if not, it presents the login form - as normal. + and finds REMOTE_USER in the environment, but does not find any forwarded + credentials, what it does is create a webkdc-proxy token using the WebKDC + keyring, with a proxy subject of "WEBKDC:remuser". + It then passes that webkdc-proxy token in to the WebKDC in an initial + request and sees if it gets back the desired tokens based on the strength + of that webkdc-proxy token. If it does, it proceeds to the confirmation + screen; if not, it presents the login form as normal. The special prefix "WEBKDC:" in a webkdc-proxy token is used to represent single sign-on tokens, so this is a webkdc-proxy token of type @@ -130,3 +146,7 @@ This webkdc-proxy token is never stored in a cookie, to force reauthentication with SPNEGO on each visit. + + However, if a TGT has been forwarded, the TGT is used instead of a username + and password. The user then is authenticated exactly as they were + using username and password. diff -ru webauth-3.5.5.orig/doc/protocol.xml webauth-3.5.5/doc/protocol.xml --- webauth-3.5.5.orig/doc/protocol.xml 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/doc/protocol.xml 2008-02-19 21:34:23.000000000 +0100 @@ -1816,15 +1816,29 @@ <section anchor='tokenlogin' title='login Token Encoding'> <t>A login token is used by the Weblogin component of the WebKDC to communicate a username and password to the rest of the - WebKDC when it needs to authenticate a user.</t> + WebKDC when it needs to authenticate a user. + Credential type and credential data are then unset.</t> + + <t>Alternatively, a forwarded Kerberos ticket may be used + instead of a username and password. In this case, username and + password remain unset, credential type contains "krb5", + and credential data contains a TGT.</t> + + <t>For the alternative to work, the webkdc's web-server + must be configured to accept Kerberos authentication. + The WebKDC itself must accept Remote-User authentication, + and the client's web-browser must have ticket forwarding + enabled to the Weblogin URL.</t> <figure> <preamble>Token format:</preamble> <artwork> t=login ct={creation-time} - p={password} - u={username} + [p={password}] + [u={username}] + [crt={credential type}] + [crd={credential data}] </artwork> </figure> diff -ru webauth-3.5.5.orig/src/libwebauth/krb5.c webauth-3.5.5/src/libwebauth/krb5.c --- webauth-3.5.5.orig/src/libwebauth/krb5.c 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/libwebauth/krb5.c 2008-02-19 22:20:32.000000000 +0100 @@ -232,6 +232,15 @@ return (c->code == 0) ? WA_ERR_NONE : WA_ERR_KRB5; } +int +webauth_krb5_verify_tgt(WEBAUTH_KRB5_CTXT *context, + const char *keytab, + const char *server_principal, + char **server_principal_out) +{ + return verify_tgt( (WEBAUTH_KRB5_CTXTP*) context, keytab, + server_principal, server_principal_out); +} /* ** Create a new WEBAUTH_KRB5_CTXT. diff -ru webauth-3.5.5.orig/src/libwebauth/libwebauth.def webauth-3.5.5/src/libwebauth/libwebauth.def --- webauth-3.5.5.orig/src/libwebauth/libwebauth.def 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/libwebauth/libwebauth.def 2008-02-17 20:44:57.000000000 +0100 @@ -7,6 +7,7 @@ ;DESCRIPTION 'WebAuth libwebauth - http://webauth.stanford.edu' EXPORTS + webauth_krb5_verify_tgt webauth_attr_list_new webauth_error_message webauth_info_version diff -ru webauth-3.5.5.orig/src/libwebauth/mapfile webauth-3.5.5/src/libwebauth/mapfile --- webauth-3.5.5.orig/src/libwebauth/mapfile 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/libwebauth/mapfile 2008-02-17 20:44:57.000000000 +0100 @@ -1,5 +1,6 @@ WEBAUTH_1.0 { global: + webauth_krb5_verify_tgt; webauth_attr_list_new; webauth_error_message; webauth_info_version; diff -ru webauth-3.5.5.orig/src/libwebauth/webauth.h.in webauth-3.5.5/src/libwebauth/webauth.h.in --- webauth-3.5.5.orig/src/libwebauth/webauth.h.in 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/libwebauth/webauth.h.in 2008-02-17 20:44:57.000000000 +0100 @@ -759,6 +759,16 @@ /******************** krb5 ********************/ +/* + * Verify a Kerberos TGT (stored in the context) by obtaining a service + * ticket for the principal stored in our local keytab and then verifying + * that service ticket is correct. + * + */ +WEBAUTH_API int webauth_krb5_verify_tgt(WEBAUTH_KRB5_CTXT *context, + const char *keytab, + const char *server_principal, + char **server_principal_out); /* * create new webauth krb5 context for use with all the webauth_krb5_* diff -ru webauth-3.5.5.orig/src/modules/webkdc/mod_webkdc.c webauth-3.5.5/src/modules/webkdc/mod_webkdc.c --- webauth-3.5.5.orig/src/modules/webkdc/mod_webkdc.c 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/modules/webkdc/mod_webkdc.c 2008-02-19 22:26:38.000000000 +0100 @@ -627,6 +627,25 @@ goto cleanup; } lt->password = apr_pstrdup(rc->r->pool, (char*)alist->attrs[i].value); + + /* pull out credential-type */ + status = webauth_attr_list_find(alist, WA_TK_CRED_TYPE, &i); + if (i == -1) { + set_errorResponse(rc, WA_PEC_LOGIN_TOKEN_INVALID, + "missing credential-type", mwk_func, 1); + goto cleanup; + } + lt->cred_type = apr_pstrdup(rc->r->pool, (char*)alist->attrs[i].value); + + /* pull out ticket */ + status = webauth_attr_list_find(alist, WA_TK_CRED_DATA, &i); + if (i == -1) { + set_errorResponse(rc, WA_PEC_LOGIN_TOKEN_INVALID, + "missing ticket", mwk_func, 1); + goto cleanup; + } + lt->cred = apr_pstrdup(rc->r->pool, (char*)alist->attrs[i].value); + ms = MWK_OK; cleanup: @@ -1902,6 +1921,188 @@ } static enum mwk_status +mwk_do_auto_login_krb5(MWK_REQ_CTXT *rc, + MWK_LOGIN_TOKEN *lt, + MWK_SUBJECT_CREDENTIAL *sub_cred, + MWK_RETURNED_PROXY_TOKEN rtokens[], + int *num_rtokens, + char **subject_out) +{ + static const char*mwk_func = "mwk_do_login"; + WEBAUTH_KRB5_CTXT *ctxt; + char *subject, *server_principal; + int status, tgt_len, len; + enum mwk_status ms; + time_t tgt_expiration, creation; + char *tgt; + MWK_PROXY_TOKEN *pt; + WEBAUTH_ATTR_LIST *alist; + + *subject_out = NULL; + + ms = MWK_ERROR; + + ctxt = mwk_get_webauth_krb5_ctxt(rc->r, mwk_func); + if (ctxt == NULL) { + /* mwk_get_webauth_krb5_ctxt already logged error */ + return set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "server failure", mwk_func, 0); + } + + status = webauth_base64_decoded_length(lt->cred,strlen(lt->cred),&tgt_len); + if (status != WA_ERR_NONE) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "webauth_base64_decoded_length failed", mwk_func, 0); + goto cleanup; + } + + tgt = (char *) apr_palloc(rc->r->pool, tgt_len); + if (tgt == NULL) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "cannot alloc memory", mwk_func, 0); + goto cleanup; + } + + status = webauth_base64_decode(lt->cred, strlen(lt->cred), tgt, &tgt_len, tgt_len); + if (status != WA_ERR_NONE) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "webauth_base64_decode failed", mwk_func, 0); + goto cleanup; + } + + status = webauth_krb5_init_via_cred(ctxt, tgt, tgt_len, NULL); + if (status == WA_ERR_NONE) { + status = webauth_krb5_verify_tgt(ctxt, + rc->sconf->keytab_path, + rc->sconf->keytab_principal, + &server_principal); + } + + if (status != WA_ERR_NONE) { + char *msg = mwk_webauth_error_message(rc->r, status, ctxt, + "webauth_krb5_init_via_cred", + NULL); + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, msg, mwk_func, 1); + goto cleanup; + } else { + /* copy libc malloc'ed server_principal to apache memory pool */ + char *temp = apr_pstrcat(rc->r->pool, "krb5:", server_principal, NULL); + free(server_principal); + if (temp == NULL) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "cannot alloc memory", mwk_func, 0); + goto cleanup; + } + server_principal = temp; + } + + + /* get subject, attempt local-name conversion */ + status = webauth_krb5_get_principal(ctxt, &subject, 1); + if (status != WA_ERR_NONE) { + char *msg = mwk_webauth_error_message(rc->r, status, ctxt, + "webauth_krb5_get_principal", + NULL); + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, msg, mwk_func, 1); + goto cleanup; + } else { + char *new_subject = apr_pstrdup(rc->r->pool, subject); + free(subject); + if (new_subject == NULL) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "cannot alloc memory", mwk_func, 0); + goto cleanup; + } + subject = new_subject; + } + + *subject_out = subject; + + /* export TGT for webkdc-proxy-token */ + status = webauth_krb5_export_tgt(ctxt, &tgt, &tgt_len, &tgt_expiration); + if (status != WA_ERR_NONE) { + char *msg = mwk_webauth_error_message(rc->r, status, ctxt, + "webauth_krb5_export_tgt", + NULL); + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, msg, mwk_func, 1); + goto cleanup; + } else { + char *new_tgt = apr_palloc(rc->r->pool, tgt_len); + if (new_tgt == NULL) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "cannot alloc memory", mwk_func, 0); + goto cleanup; + } + memcpy(new_tgt, tgt, tgt_len); + free(tgt); + tgt = new_tgt; + } + + /* We now have everything we need to create the webkdc-proxy-token. + * Let's store the data into the SUBJECT_CREDENTIAL sub_cred. + * Use it to create a token. Return this token. + * + * we've already copied all this stuff into a pool, so there is no + * need to copy again... + */ + + pt = &sub_cred->u.proxy.pt[0]; + + pt->proxy_type = "krb5"; + /* pt->proxy_subject = server_principal;*/ + pt->proxy_subject = apr_pstrcat(rc->r->pool, "WEBKDC:", + server_principal, NULL); + if (pt->proxy_subject == NULL) { + set_errorResponse(rc, WA_PEC_SERVER_FAILURE, + "cannot alloc memory", mwk_func, 0); + goto cleanup; + } + pt->subject = subject; + pt->proxy_data = tgt; + pt->proxy_data_len = tgt_len; + + time(&creation); + + /* Use minimum lifespan of ProxyTokenLifetime + and the tgt unless ProxyTokenLifetime is 0. + Otherwise use tgt lifetime */ + if (rc->sconf->proxy_token_lifetime) { + time_t pmax = creation + rc->sconf->proxy_token_lifetime; + pt->expiration = (tgt_expiration < pmax) ? tgt_expiration : pmax; + } else { + pt->expiration = tgt_expiration; + } + + alist = new_attr_list(rc, mwk_func); + if (alist == NULL) + goto cleanup; + + SET_TOKEN_TYPE(WA_TT_WEBKDC_PROXY); + SET_PROXY_SUBJECT(pt->proxy_subject); + SET_PROXY_TYPE(pt->proxy_type); + SET_SUBJECT(pt->subject); + SET_PROXY_DATA(tgt, tgt_len); + SET_CREATION_TIME(creation); + SET_EXPIRATION_TIME(pt->expiration); + + ms = make_token(rc, alist, creation, + (char**)&rtokens[0].token_data, &len, 1, mwk_func); + if (ms == MWK_OK) { + rtokens[0].type = pt->proxy_type; + *num_rtokens = 1; + sub_cred->u.proxy.num_proxy_tokens = 1; + /* make sure we fill in type! */ + sub_cred->type = "proxy"; + } + + webauth_attr_list_free(alist); + + cleanup: + + webauth_krb5_free(ctxt); + return ms; +} +static enum mwk_status parse_requestInfo(MWK_REQ_CTXT *rc, apr_xml_elem *e, MWK_REQUEST_INFO *req_info) { @@ -2048,23 +2249,41 @@ * and if that succeeds, we'll get a new MWK_SUBJECT_CREDENTIAL * to pass around, and new proxy-tokens to set. * + * + * Some WAS may request the user to explicitly authenticate + * with username and password. + * For users who have autheticated with passwords, did_login will + * be set to 1. For all others, did_login will be 0. + * Thus, users authenticating automatically with TGT forwarding + * (without passwords) will have did_login=0 and will still be + * prompted for passwords in favour of such services. + * */ - if (strcmp(parsed_sub_cred.type, "login") == 0) { - if (!mwk_do_login(rc, &parsed_sub_cred.u.lt, &login_sub_cred, - rptokens, &num_proxy_tokens, subject_out)) { - *subject_out = parsed_sub_cred.u.lt.username; - if (rc->error_code == WA_PEC_LOGIN_FAILED) { - login_ec = rc->error_code; - login_em = rc->error_message; - rc->error_code = 0; - rc->error_message = NULL; - goto send_response; - } else { + if (strcmp(parsed_sub_cred.type, "login") == 0) { + if (strlen(parsed_sub_cred.u.lt.username)) { + if (!mwk_do_login(rc, &parsed_sub_cred.u.lt, &login_sub_cred, + rptokens, &num_proxy_tokens, subject_out)) { + *subject_out = parsed_sub_cred.u.lt.username; + if (rc->error_code == WA_PEC_LOGIN_FAILED) { + login_ec = rc->error_code; + login_em = rc->error_message; + rc->error_code = 0; + rc->error_message = NULL; + goto send_response; + } else { + return MWK_ERROR; + } + } + sub_cred = &login_sub_cred; + did_login = 1; + } else if (strcmp("krb5",parsed_sub_cred.u.lt.cred_type) == 0) { + if (!mwk_do_auto_login_krb5(rc, &parsed_sub_cred.u.lt, &login_sub_cred, + rptokens, &num_proxy_tokens, subject_out)) { return MWK_ERROR; } + sub_cred = &login_sub_cred; + did_login = 0; } - sub_cred = &login_sub_cred; - did_login = 1; } else { sub_cred = &parsed_sub_cred; /* grab first subject from passed in proxy tokens as subject_out */ diff -ru webauth-3.5.5.orig/src/modules/webkdc/mod_webkdc.h webauth-3.5.5/src/modules/webkdc/mod_webkdc.h --- webauth-3.5.5.orig/src/modules/webkdc/mod_webkdc.h 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/modules/webkdc/mod_webkdc.h 2008-02-17 20:44:57.000000000 +0100 @@ -157,6 +157,8 @@ typedef struct { char *username; char *password; + char *cred_type; + char *cred; } MWK_LOGIN_TOKEN; /* interesting stuff from a parsed request-token */ diff -ru webauth-3.5.5.orig/src/webkdc/login.fcgi webauth-3.5.5/src/webkdc/login.fcgi --- webauth-3.5.5.orig/src/webkdc/login.fcgi 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/webkdc/login.fcgi 2008-02-19 20:47:29.000000000 +0100 @@ -304,8 +304,17 @@ } } + # if external SSO is in effect (ticket forwarding in the browser to + # the webkdc) don't show informational message about WebAuth SSO. + # The user can reauthenticate without supplying a password at any time, + # so don't bother about telling him to log out. + # (except if an application offers a cancel login button) + if ($lvars->{forwarded_cred} && !$lc) { + print_headers ($q, $resp->proxy_cookies, $return_url); + } else { + print_headers ($q, $resp->proxy_cookies); + } # Print out the page, including any updated proxy cookies if needed. - print_headers ($q, $resp->proxy_cookies); print $page->output; } @@ -571,6 +580,35 @@ } $req->remote_user ($ENV{REMOTE_USER}); + # if the webkdc's apache server has been setup to accept kerberos + # authentication and the web browser has been setup to forward tickets, + # and HONOR_REMOTE_USER is configured, then use the forwarded + # credentials. + # + # If we already have a username and password, we must have already + # passed here and failed. Consequently the login page had been displayed + # and users have entered passwords and usernames. + # If this is the case, skip this step and authenticate users + # using their username / password. + + my $forwarded_cred=0; + if (!$q->param('password') && !$q->param('username') && $WebKDC::Config::HONOR_REMOTE_USER && $ENV{KRB5CCNAME}) { + my $c = WebAuth::krb5_new(); + krb5_init_via_cache($c); + my $ctx_princ = WebAuth::krb5_get_principal($c, 0); + + if ($ctx_princ ne $ENV{REMOTE_USER}) { + print STDERR ("Ignoring Tickets from $ENV{KRB5CCNAME}: PRINC=$ctx_princ (KRB5 Ticket) differs from REMOTE_USER=$ENV{REMOTE_USER} (Apache)\n") + if $LOGGING; + } else { + my ($tgt, $expiration) = WebAuth::krb5_export_tgt($c); + my $tgt_enc = base64_encode($tgt); + $req->cred_data ($tgt_enc); + $req->cred_type ("krb5"); + $forwarded_cred = 1; + } + } + # Pass the information along to the WebKDC and get the repsonse. ($status, $exception) = WebKDC::make_request_token_request ($req, $resp); @@ -578,6 +616,7 @@ # any. (The login cancel stuff is oddly placed here, like it was added as # an afterthought, and should probably be handled in a cleaner fashion.) my %varhash = map { $_ => $q->param ($_) } $q->param; + $varhash{forwarded_cred} = $forwarded_cred; get_login_cancel_url (\%varhash, $resp); if ($status == WK_SUCCESS && parse_uri (\%varhash, $resp)) { $status = WK_ERR_WEBAUTH_SERVER_ERROR; diff -ru webauth-3.5.5.orig/src/webkdc/WebKDC/Token.pm webauth-3.5.5/src/webkdc/WebKDC/Token.pm --- webauth-3.5.5.orig/src/webkdc/WebKDC/Token.pm 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/webkdc/WebKDC/Token.pm 2008-02-17 20:44:57.000000000 +0100 @@ -378,6 +378,18 @@ return $self->{'attrs'}{&WA_TK_PASSWORD}; } +sub cred_type { + my $self = shift; + $self->{'attrs'}{&WA_TK_CRED_TYPE} = shift if @_; + return $self->{'attrs'}{&WA_TK_CRED_TYPE}; +} + +sub cred_data { + my $self = shift; + $self->{'attrs'}{&WA_TK_CRED_DATA} = shift if @_; + return $self->{'attrs'}{&WA_TK_CRED_DATA}; +} + sub creation_time { my $self = shift; $self->{'attrs'}{&WA_TK_CREATION_TIME} = pack("N", shift) if @_; @@ -393,8 +405,8 @@ croak "validate_token failed" unless ($self->token_type() eq 'login') && - defined($self->username) && - defined($self->password); + (( defined($self->username) && defined($self->password)) || + ( defined($self->cred_data ) && defined($self->cred_type))) ; } ############################################################ diff -ru webauth-3.5.5.orig/src/webkdc/WebKDC/WebRequest.pm webauth-3.5.5/src/webkdc/WebKDC/WebRequest.pm --- webauth-3.5.5.orig/src/webkdc/WebKDC/WebRequest.pm 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/webkdc/WebKDC/WebRequest.pm 2008-02-17 20:44:57.000000000 +0100 @@ -39,6 +39,18 @@ return $self->{'pass'}; } +sub cred_data { + my $self = shift; + $self->{'cred_data'} = shift if @_; + return $self->{'cred_data'}; +} + +sub cred_type { + my $self = shift; + $self->{'cred_type'} = shift if @_; + return $self->{'cred_type'}; +} + sub proxy_cookie { my $self = shift; my $type = shift; diff -ru webauth-3.5.5.orig/src/webkdc/WebKDC.pm webauth-3.5.5/src/webkdc/WebKDC.pm --- webauth-3.5.5.orig/src/webkdc/WebKDC.pm 2008-01-15 01:54:39.000000000 +0100 +++ webauth-3.5.5/src/webkdc/WebKDC.pm 2008-02-17 20:44:57.000000000 +0100 @@ -102,7 +102,7 @@ sub request_token_request($$) { my ($wreq, $wresp) = @_; - my ($user, $pass) = ($wreq->user(), $wreq->pass()); + my ($user, $pass, $cred_data, $cred_type) = ($wreq->user(), $wreq->pass(), $wreq->cred_data(), $wreq->cred_type()); my $request_token = $wreq->request_token(); my $service_token = $wreq->service_token(); my $proxy_cookies = $wreq->proxy_cookies(); @@ -116,13 +116,15 @@ $service_token)->end; $webkdc_doc->start('subjectCredential'); - if (defined($user)) { + if (defined($user) || defined($cred_data)) { # need to make a login token $webkdc_doc->current->attr('type','login'); my $login_token = new WebKDC::LoginToken; $login_token->password($pass); $login_token->username($user); + $login_token->cred_data($cred_data); + $login_token->cred_type($cred_type); $login_token->creation_time(time()); # FIXME: DEBUGGING!