Handle HTTP redirections automatically.
[doldaconnect.git] / daemon / auth-krb5.c
index 62827c6..7b88af3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Dolda Connect - Modular multiuser Direct Connect-style client
- *  Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
+ *  Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -266,7 +266,7 @@ static void setrenew(struct krb5data *data)
     data->renewtimer = timercallback(good, (void (*)(int, void *))renewcreds, data);
 }
 
-static int krbauth(struct authhandle *auth, char *passdata)
+static int krbauth(struct authhandle *auth, struct socket *sk, char *passdata)
 {
     int ret;
     struct krb5data *data;
@@ -305,6 +305,7 @@ static int krbauth(struct authhandle *auth, char *passdata)
                if(auth->text != NULL)
                    free(auth->text);
                auth->text = icmbstowcs((char *)error_message(ret), NULL);
+               free(msg);
                return(AUTH_DENIED);
            }
            free(msg);
@@ -348,7 +349,7 @@ static int krbauth(struct authhandle *auth, char *passdata)
                    authorized = 1;
                if(authorized)
                {
-                   flog(LOG_INFO, "krb5 principal %s successfully authorized as %s", data->cname, data->username);
+                   flog(LOG_INFO, "krb5 principal %s successfully authorized as %s%s", data->cname, data->username, (data->creds == NULL)?"":" (with fwd creds)");
                    return(AUTH_SUCCESS);
                } else {
                    flog(LOG_INFO, "krb5 principal %s not authorized as %s", data->cname, data->username);
@@ -369,15 +370,16 @@ static int krbauth(struct authhandle *auth, char *passdata)
            if((ret = krb5_rd_cred(k5context, data->context, &k5d, &fwdcreds, NULL)) != 0)
            {
                flog(LOG_ERR, "krb5_rd_cred returned an error: %s", error_message(ret));
+               free(msg);
                return(AUTH_ERR);
            }
+           free(msg);
            if(*fwdcreds == NULL)
            {
                flog(LOG_ERR, "forwarded credentials array was empty (from %s)", data->username);
                krb5_free_tgt_creds(k5context, fwdcreds);
                return(AUTH_ERR);
            }
-           flog(LOG_INFO, "received forwarded credentials for %s", data->username);
            /* Copy only the first credential. (Change this if it becomes a problem) */
            ret = krb5_copy_creds(k5context, *fwdcreds, &data->creds);
            krb5_free_tgt_creds(k5context, fwdcreds);
@@ -420,43 +422,67 @@ static int opensess(struct authhandle *auth)
            flog(LOG_ERR, "could not get passwd entry for forwarded tickets (user %s): %s", data->username, strerror(errno));
            return(AUTH_ERR);
        }
-       buf = sprintf2("/tmp/krb5cc_dc_%i_XXXXXX", pwent->pw_uid);
-       if((fd = mkstemp(buf)) < 0)
-       {
-           free(buf);
-           flog(LOG_ERR, "could not create temporary file for ccache: %s", strerror(errno));
-           return(AUTH_ERR);
-       }
-       close(fd);
-       buf2 = sprintf2("FILE:%s", buf);
-       if((ret = krb5_cc_resolve(k5context, buf2, &data->ccache)) != 0)
+       if(!confgetint("auth-krb5", "usedefcc"))
        {
-           free(buf);
+           buf = sprintf2("/tmp/krb5cc_dc_%i_XXXXXX", pwent->pw_uid);
+           if((fd = mkstemp(buf)) < 0)
+           {
+               free(buf);
+               flog(LOG_ERR, "could not create temporary file for ccache: %s", strerror(errno));
+               return(AUTH_ERR);
+           }
+           close(fd);
+           buf2 = sprintf2("FILE:%s", buf);
+           if((ret = krb5_cc_resolve(k5context, buf2, &data->ccache)) != 0)
+           {
+               free(buf);
+               free(buf2);
+               flog(LOG_ERR, "could not resolve ccache name \"%s\": %s", buf2, error_message(ret));
+               return(AUTH_ERR);
+           }
+           setenv("KRB5CCNAME", buf2, 1);
            free(buf2);
-           flog(LOG_ERR, "could not resolve ccache name \"%s\": %s", buf2, error_message(ret));
-           return(AUTH_ERR);
-       }
-       setenv("KRB5CCNAME", buf2, 1);
-       free(buf2);
-       if((ret = krb5_cc_initialize(k5context, data->ccache, data->ticket->enc_part2->client)) != 0)
-       {
-           free(buf);
-           flog(LOG_ERR, "could not initialize ccache: %s", error_message(ret));
-           return(AUTH_ERR);
-       }
-       if((ret = krb5_cc_store_cred(k5context, data->ccache, data->creds)) != 0)
-       {
-           free(buf);
-           flog(LOG_ERR, "could not store forwarded TGT into ccache: %s", error_message(ret));
-           return(AUTH_ERR);
-       }
-       if(chown(buf, pwent->pw_uid, pwent->pw_gid))
-       {
+           if((ret = krb5_cc_initialize(k5context, data->ccache, data->ticket->enc_part2->client)) != 0)
+           {
+               free(buf);
+               flog(LOG_ERR, "could not initialize ccache: %s", error_message(ret));
+               return(AUTH_ERR);
+           }
+           if((ret = krb5_cc_store_cred(k5context, data->ccache, data->creds)) != 0)
+           {
+               free(buf);
+               flog(LOG_ERR, "could not store forwarded TGT into ccache: %s", error_message(ret));
+               return(AUTH_ERR);
+           }
+           if(chown(buf, pwent->pw_uid, pwent->pw_gid))
+           {
+               free(buf);
+               flog(LOG_ERR, "could not chown new ccache to %i:%i: %s", pwent->pw_uid, pwent->pw_gid, strerror(errno));
+               return(AUTH_ERR);
+           }
            free(buf);
-           flog(LOG_ERR, "could not chown new ccache to %i:%i: %s", pwent->pw_uid, pwent->pw_gid, strerror(errno));
-           return(AUTH_ERR);
+       } else {
+           if((buf = (char *)krb5_cc_default_name(k5context)) == NULL) {
+               flog(LOG_ERR, "could not get default ccache name");
+               return(AUTH_ERR);
+           }
+           if((ret = krb5_cc_resolve(k5context, buf, &data->ccache)) != 0)
+           {
+               flog(LOG_ERR, "could not resolve ccache name \"%s\": %s", buf, error_message(ret));
+               return(AUTH_ERR);
+           }
+           setenv("KRB5CCNAME", buf, 1);
+           if((ret = krb5_cc_initialize(k5context, data->ccache, data->ticket->enc_part2->client)) != 0)
+           {
+               flog(LOG_ERR, "could not initialize ccache: %s", error_message(ret));
+               return(AUTH_ERR);
+           }
+           if((ret = krb5_cc_store_cred(k5context, data->ccache, data->creds)) != 0)
+           {
+               flog(LOG_ERR, "could not store forwarded TGT into ccache: %s", error_message(ret));
+               return(AUTH_ERR);
+           }
        }
-       free(buf);
     }
     return(AUTH_SUCCESS);
 }
@@ -568,9 +594,20 @@ static void terminate(void)
 
 static struct configvar myvars[] =
 {
+    /** The name of the service principal to use for Kerberos V
+     * authentication. */
     {CONF_VAR_STRING, "service", {.str = L"doldacond"}},
+    /** The path to an alternative keytab file. If unspecified, the
+     * system default keytab will be used. */
     {CONF_VAR_STRING, "keytab", {.str = L""}},
+    /** Whether to renew renewable credentials automatically before
+     * they expire. */
     {CONF_VAR_BOOL, "renewcreds", {.num = 1}},
+    /** If true, the default credentials cache will be used, which is
+     * useful for e.g. Linux kernel key handling. If false, a file
+     * credentials cache will be created using mkstemp(3), using the
+     * pattern /tmp/krb5cc_dc_$UID_XXXXXX. */
+    {CONF_VAR_BOOL, "usedefcc", {.num = 0}},
     {CONF_VAR_END}
 };