- kerb_auth_config *conf =
- (kerb_auth_config *)ap_get_module_config(r->per_dir_config,
- &auth_kerb_module);
- int ret;
- int lifetime = DEFAULT_TKT_LIFE;
- char *c, *tfname;
- char *username = NULL;
- char *instance = NULL;
- char *realm = NULL;
-
- username = (char *)ap_pstrdup(r->pool, user);
- if (!username) {
- return 0;
- }
-
- instance = strchr(username, '.');
- if (instance) {
- *instance++ = '\0';
- }
- else {
- instance = "";
- }
-
- realm = strchr(username, '@');
- if (realm) {
- *realm++ = '\0';
- }
- else {
- realm = "";
- }
-
- if (conf->krb_lifetime) {
- lifetime = atoi(conf->krb_lifetime);
- }
-
- if (conf->krb_force_instance) {
- instance = conf->krb_force_instance;
- }
-
- if (conf->krb_save_credentials) {
- tfname = (char *)malloc(sizeof(char) * MAX_STRING_LEN);
- sprintf(tfname, "/tmp/k5cc_ap_%s", MK_USER);
-
- if (!strcmp(instance, "")) {
- tfname = strcat(tfname, ".");
- tfname = strcat(tfname, instance);
- }
-
- if (!strcmp(realm, "")) {
- tfname = strcat(tfname, ".");
- tfname = strcat(tfname, realm);
- }
-
- for (c = tfname + strlen("/tmp") + 1; *c; c++) {
- if (*c == '/')
- *c = '.';
- }
-
- krb_set_tkt_string(tfname);
- }
-
- if (!strcmp(realm, "")) {
- realm = (char *)malloc(sizeof(char) * (REALM_SZ + 1));
- ret = krb_get_lrealm(realm, 1);
- if (ret != KSUCCESS)
- return 0;
- }
-
- ret = krb_get_pw_in_tkt((char *)user, instance, realm, "krbtgt", realm,
- lifetime, (char *)pass);
- switch (ret) {
- case INTK_OK:
- case INTK_W_NOTALL:
- return 1;
- break;
-
- default:
- return 0;
- break;
- }
+ int ret;
+ char *phost;
+ unsigned long addr;
+ struct hostent *hp;
+ const char *hostname;
+ KTEXT_ST ticket;
+ AUTH_DAT authdata;
+ char lrealm[REALM_SZ];
+
+ ret = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm,
+ DEFAULT_TKT_LIFE, password);
+ if (ret) {
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Cannot get krb4 ticket: krb_get_pw_in_tkt() failed: %s",
+ krb_get_err_text(ret));
+ return ret;
+ }
+
+ if (!krb_verify_kdc)
+ return ret;
+
+ hostname = ap_get_server_name(r);
+
+ hp = gethostbyname(hostname);
+ if (hp == NULL) {
+ dest_tkt();
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Cannot verify krb4 ticket: gethostbyname() failed: %s",
+ hstrerror(h_errno));
+ return h_errno;
+ }
+ memcpy(&addr, hp->h_addr, sizeof(addr));
+
+ phost = krb_get_phost((char *)hostname);
+
+ krb_get_lrealm(lrealm, 1);
+
+ ret = krb_mk_req(&ticket, linstance, phost, lrealm, 0);
+ if (ret) {
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Cannot verify krb4 ticket: krb_mk_req() failed: %s",
+ krb_get_err_text(ret));
+ dest_tkt();
+ return ret;
+ }
+
+ ret = krb_rd_req(&ticket, linstance, phost, addr, &authdata, srvtab);
+ if (ret) {
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Cannot verify krb4 ticket: krb_rd_req() failed: %s",
+ krb_get_err_text(ret));
+ dest_tkt();
+ }
+
+ return ret;
+}
+
+static int
+krb4_cache_cleanup(void *data)
+{
+ char *tkt_file = (char *) data;
+
+ krb_set_tkt_string(tkt_file);
+ dest_tkt();
+ return OK;
+}
+
+static int
+authenticate_user_krb4pwd(request_rec *r,
+ kerb_auth_config *conf,
+ const char *auth_line)
+{
+ int ret;
+ const char *sent_pw;
+ const char *sent_name;
+ char *sent_instance;
+ char tkt_file[32];
+ char *tkt_file_p = NULL;
+ int fd;
+ const char *realms;
+ const char *realm;
+ char *user;
+ char lrealm[REALM_SZ];
+ int all_principals_unkown;
+
+ sent_pw = ap_pbase64decode(r->pool, auth_line);
+ sent_name = ap_getword (r->pool, &sent_pw, ':');
+
+ /* do not allow user to override realm setting of server */
+ if (ap_strchr_c(sent_name, '@')) {
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "specifying realm in user name is prohibited");
+ return HTTP_UNAUTHORIZED;
+ }
+
+ sent_instance = strchr(sent_name, '.');
+ if (sent_instance)
+ *sent_instance++ = '\0';
+
+ snprintf(tkt_file, sizeof(tkt_file), "/tmp/apache_tkt_XXXXXX");
+ fd = mkstemp(tkt_file);
+ if (fd < 0) {
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+ "Cannot create krb4 ccache: mkstemp() failed: %s",
+ strerror(errno));
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ tkt_file_p = ap_pstrdup(r->pool, tkt_file);
+ ap_register_cleanup(r->pool, tkt_file_p,
+ krb4_cache_cleanup, ap_null_cleanup);
+
+ krb_set_tkt_string(tkt_file);
+
+ all_principals_unkown = 1;
+ realms = conf->krb_auth_realms;
+ do {
+ memset(lrealm, 0, sizeof(lrealm));
+ realm = NULL;
+ if (realms)
+ realm = ap_getword_white(r->pool, &realms);
+
+ if (realm == NULL) {
+ ret = krb_get_lrealm(lrealm, 1);
+ if (ret)
+ break;
+ realm = lrealm;
+ }
+
+ /* XXX conf->krb_service_name */
+ ret = verify_krb4_user(r, (char *)sent_name,
+ (sent_instance) ? sent_instance : "",
+ (char *)realm, (char *)sent_pw,
+ conf->krb_service_name,
+ conf->krb_4_srvtab, conf->krb_verify_kdc);
+ if (!conf->krb_authoritative && ret) {
+ /* if we're not authoritative, we allow authentication to pass on
+ * to another modules if (and only if) the user is not known to us */
+ if (all_principals_unkown && ret != KDC_PR_UNKNOWN)
+ all_principals_unkown = 0;
+ }
+
+ if (ret == 0)
+ break;
+ } while (realms && *realms);
+
+ if (ret) {
+ /* XXX log only in the verify_krb4_user() call */
+ log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Verifying krb4 password failed");
+ ret = (!conf->krb_authoritative && all_principals_unkown == 1 && ret == KDC_PR_UNKNOWN) ?
+ DECLINED : HTTP_UNAUTHORIZED;
+ goto end;
+ }
+
+ user = ap_pstrdup(r->pool, sent_name);
+ if (sent_instance)
+ user = ap_pstrcat(r->pool, user, ".", sent_instance, NULL);
+ user = ap_pstrcat(r->pool, user, "@", realm, NULL);
+
+ MK_USER = user;
+ MK_AUTH_TYPE = "Basic";
+ ap_table_setn(r->subprocess_env, "KRBTKFILE", tkt_file_p);
+
+ if (!conf->krb_save_credentials)
+ krb4_cache_cleanup(tkt_file);
+
+end:
+ if (ret)
+ krb4_cache_cleanup(tkt_file);
+ close(fd);
+ tf_close();
+
+ return ret;