venus: Remove dedebug
[openafs.git] / src / aklog / klog.c
index 3a8eff6..6a75399 100644 (file)
@@ -24,6 +24,7 @@
 #include <afs/cmd.h>
 #include <afs/ptuser.h>
 
+#define KERBEROS_APPLE_DEPRECATED(x)
 #include <krb5.h>
 
 #ifdef HAVE_KRB5_CREDS_KEYBLOCK
@@ -33,7 +34,6 @@
 #define USING_HEIMDAL 1
 #endif
 
-#include "assert.h"
 #include "skipwrap.h"
 
 /* This code borrowed heavily from the previous version of log.  Here is the
@@ -99,7 +99,7 @@ main(int argc, char *argv[])
     zero_argc = argc;
     zero_argv = argv;
 
-    ts = cmd_CreateSyntax(NULL, CommandProc, NULL,
+    ts = cmd_CreateSyntax(NULL, CommandProc, NULL, 0,
                          "obtain Kerberos authentication");
 
 #define aXFLAG 0
@@ -116,8 +116,9 @@ main(int argc, char *argv[])
 #define aUNWRAP 11
 #define aK5 12
 #define aK4 13
+#define aDES 14
 
-    cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, 0);
+    cmd_AddParm(ts, "-x", CMD_FLAG, CMD_OPTIONAL, "obsolete, noop");
     cmd_Seek(ts, aPRINCIPAL);
     cmd_AddParm(ts, "-principal", CMD_SINGLE, CMD_OPTIONAL, "user name");
     cmd_AddParm(ts, "-password", CMD_SINGLE, CMD_OPTIONAL, "user's password");
@@ -126,8 +127,9 @@ main(int argc, char *argv[])
     cmd_AddParm(ts, "-pipe", CMD_FLAG, CMD_OPTIONAL,
                "read password from stdin");
     cmd_AddParm(ts, "-silent", CMD_FLAG, CMD_OPTIONAL, "silent operation");
+    /* Note: -lifetime is not implemented in this version of klog. */
     cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL,
-               "ticket lifetime in hh[:mm[:ss]]");
+               "ignored (for compatibility with the krb4-based klog)");
     cmd_AddParm(ts, "-setpag", CMD_FLAG, CMD_OPTIONAL,
                "Create a new setpag before authenticating");
     cmd_AddParm(ts, "-tmp", CMD_FLAG, CMD_OPTIONAL,
@@ -141,6 +143,8 @@ main(int argc, char *argv[])
     ++ts->nParms;      /* skip -k5 */
     cmd_AddParm(ts, "-k4", CMD_FLAG, CMD_OPTIONAL|CMD_HIDDEN, 0);
 #endif
+    cmd_AddParm(ts, "-insecure_des", CMD_FLAG, CMD_OPTIONAL,
+               "enable insecure single-DES for krb5");
 
     code = cmd_Dispatch(argc, argv);
     KLOGEXIT(code);
@@ -214,7 +218,7 @@ whoami(struct ktc_token *atoken,
     int *vicep)
 {
     int code;
-    char tempname[PR_MAXNAMELEN + 1];
+    char tempname[2*PR_MAXNAMELEN];
 
     code = pr_Initialize(0, AFSDIR_CLIENT_ETC_DIRPATH, cellconfig->name);
     if (code)
@@ -243,100 +247,17 @@ k5_to_k4_name(krb5_context k5context,
            i = get_princ_len(k5context, k5princ, 1);
            if (i > MAXKTCNAMELEN-1) i = MAXKTCNAMELEN-1;
            memcpy(ktcprinc->instance, get_princ_str(k5context, k5princ, 1), i);
-           /* fall through */
+           AFS_FALLTHROUGH;
        case 1:
            i = get_princ_len(k5context, k5princ, 0);
            if (i > MAXKTCNAMELEN-1) i = MAXKTCNAMELEN-1;
            memcpy(ktcprinc->name, get_princ_str(k5context, k5princ, 0), i);
-           /* fall through */
+           AFS_FALLTHROUGH;
        case 0:
            break;
        }
 }
 
-#if defined(USING_HEIMDAL) || defined(HAVE_KRB5_PROMPT_TYPE)
-static int
-klog_is_pass_prompt(int index, krb5_context context, krb5_prompt prompts[])
-{
-    switch (prompts[index].type) {
-    case KRB5_PROMPT_TYPE_PASSWORD:
-    case KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:
-       return 1;
-    default:
-       return 0;
-    }
-}
-#elif defined(HAVE_KRB5_GET_PROMPT_TYPES)
-static int
-klog_is_pass_prompt(int index, krb5_context context, krb5_prompt prompts[])
-{
-    /* this isn't thread-safe or anything obviously; it just should be good
-     * enough to work with klog */
-    static krb5_prompt_type *types = NULL;
-    if (index == 0) {
-       types = NULL;
-    }
-    if (!types) {
-       types = krb5_get_prompt_types(context);
-    }
-    if (!types) {
-       return 0;
-    }
-    switch (types[index]) {
-    case KRB5_PROMPT_TYPE_PASSWORD:
-    case KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:
-       return 1;
-    default:
-       return 0;
-    }
-}
-#else
-static int
-klog_is_pass_prompt(int index, krb5_context context, krb5_prompt prompts[])
-{
-    /* AIX 5.3 doesn't have krb5_get_prompt_types. Neither does HP-UX, which
-     * also doesn't even define KRB5_PROMPT_TYPE_PASSWORD &co. We have no way
-     * of determining the the prompt type, so just assume it's a password */
-    return 1;
-}
-#endif
-
-/* save and reuse password.  This is necessary to make
- *  "direct to service" authentication work with most
- *  flavors of kerberos, when the afs principal has no instance.
- */
-struct kp_arg {
-    char **pp, *pstore;
-    size_t allocated;
-};
-krb5_error_code
-klog_prompter(krb5_context context,
-    void *a,
-    const char *name,
-    const char *banner,
-    int num_prompts,
-    krb5_prompt prompts[])
-{
-    krb5_error_code code;
-    int i;
-    struct kp_arg *kparg = (struct kp_arg *) a;
-    size_t length;
-
-    code = krb5_prompter_posix(context, a, name, banner, num_prompts, prompts);
-    if (code) return code;
-    for (i = 0; i < num_prompts; ++i) {
-       if (klog_is_pass_prompt(i, context, prompts)) {
-           length = prompts[i].reply->length;
-           if (length > kparg->allocated - 1)
-               length = kparg->allocated - 1;
-           memcpy(kparg->pstore, prompts[i].reply->data, length);
-           kparg->pstore[length] = 0;
-           *kparg->pp = kparg->pstore;
-       }
-    }
-    return 0;
-}
-
 static int
 CommandProc(struct cmd_syndesc *as, void *arock)
 {
@@ -358,11 +279,7 @@ CommandProc(struct cmd_syndesc *as, void *arock)
     int authtype;
 #endif
     krb5_data enc_part[1];
-    time_t lifetime;           /* requested ticket lifetime */
-    krb5_prompter_fct pf = NULL;
     char *pass = 0;
-    void *pa = 0;
-    struct kp_arg klog_arg[1];
 
     char passwd[BUFSIZ];
     struct afsconf_cell cellconfig[1];
@@ -379,7 +296,6 @@ CommandProc(struct cmd_syndesc *as, void *arock)
     for (i = 1; i < zero_argc; i++)
        memset(zero_argv[i], 0, strlen(zero_argv[i]));
     zero_argc = 0;
-    memset(klog_arg, 0, sizeof *klog_arg);
 
     /* first determine quiet flag based on -silent switch */
     Silent = (as->parms[aSILENT].items ? 1 : 0);
@@ -413,13 +329,15 @@ CommandProc(struct cmd_syndesc *as, void *arock)
      * krb5_allow_weak_crypto is MIT Kerberos 1.8.  krb5_enctype_enable is
      * Heimdal.
      */
+    if (as->parms[aDES].items) {
 #if defined(HAVE_KRB5_ENCTYPE_ENABLE)
-    i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC);
-    if (i)
-        krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC);
+       i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC);
+       if (i)
+           krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC);
 #elif defined(HAVE_KRB5_ALLOW_WEAK_CRYPTO)
-    krb5_allow_weak_crypto(k5context, 1);
+       krb5_allow_weak_crypto(k5context, 1);
 #endif
+    }
 
     /* Parse remaining arguments. */
 
@@ -508,45 +426,10 @@ CommandProc(struct cmd_syndesc *as, void *arock)
        pass = passwd;
     }
 
-    if (as->parms[aLIFETIME].items) {
-       char *life = as->parms[aLIFETIME].items->data;
-       char *sp;               /* string ptr to rest of life */
-       lifetime = 3600 * strtol(life, &sp, 0); /* hours */
-       if (sp == life) {
-         bad_lifetime:
-           if (!Silent)
-               fprintf(stderr, "%s: translating '%s' to lifetime failed\n",
-                       rn, life);
-           return 1;
-       }
-       if (*sp == ':') {
-           life = sp + 1;      /* skip the colon */
-           lifetime += 60 * strtol(life, &sp, 0);      /* minutes */
-           if (sp == life)
-               goto bad_lifetime;
-           if (*sp == ':') {
-               life = sp + 1;
-               lifetime += strtol(life, &sp, 0);       /* seconds */
-               if (sp == life)
-                   goto bad_lifetime;
-               if (*sp)
-                   goto bad_lifetime;
-           } else if (*sp)
-               goto bad_lifetime;
-       } else if (*sp)
-           goto bad_lifetime;
-    } else
-       lifetime = 0;
-
-    /* Get the password if it wasn't provided. */
-    if (!pass) {
-       if (Pipe) {
-           strncpy(passwd, getpipepass(), sizeof(passwd));
-           pass = passwd;
-       } else {
-           pf = klog_prompter;
-           pa = klog_arg;
-       }
+    /* Get the password from stdin if it wasn't provided. */
+    if (!pass && Pipe) {
+       strncpy(passwd, getpipepass(), sizeof(passwd));
+       pass = passwd;
     }
 
     service = 0;
@@ -557,14 +440,7 @@ CommandProc(struct cmd_syndesc *as, void *arock)
     } else
 #endif
     snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name);
-    if (writeTicketFile)
-       service = 0;
-    else
-       service = service_temp;
 
-    klog_arg->pp = &pass;
-    klog_arg->pstore = passwd;
-    klog_arg->allocated = sizeof(passwd);
     /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/
 #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
     code = krb5_get_init_creds_opt_alloc(k5context, &gic_opts);
@@ -575,30 +451,26 @@ CommandProc(struct cmd_syndesc *as, void *arock)
 #else
     krb5_get_init_creds_opt_init(gic_opts);
 #endif
+
     for (;;) {
-       code = krb5_get_init_creds_password(k5context,
+        code = krb5_get_init_creds_password(k5context,
            incred,
            princ,
            pass,
-           pf, /* prompter */
-           pa, /* data */
-           0,  /* start_time */
-           service,    /* in_tkt_service */
+           krb5_prompter_posix,        /* prompter */
+           NULL,                       /* data */
+           0,                          /* start_time */
+           0,                          /* in_tkt_service */
            gic_opts);
-       if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break;
-#ifdef AFS_RXK5
-       if (authtype & FORCE_RXK5) break;
-#endif
-       service = "afs";
+       if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN)
+            break;
     }
     memset(passwd, 0, sizeof(passwd));
     if (code) {
        char *r = 0;
        if (krb5_get_default_realm(k5context, &r))
            r = 0;
-       if (service)
-           afs_com_err(rn, code, "Unable to authenticate to use %s", service);
-       else if (r)
+       if (r)
            afs_com_err(rn, code, "Unable to authenticate in realm %s", r);
        else
            afs_com_err(rn, code, "Unable to authenticate to use cell %s",
@@ -607,63 +479,61 @@ CommandProc(struct cmd_syndesc *as, void *arock)
        KLOGEXIT(code);
     }
 
-    if (service) {
-       afscred = incred;
-    } else {
-       for (;;writeTicketFile = 0) {
-           if (writeTicketFile) {
-               what = "getting default ccache";
-               code = krb5_cc_default(k5context, &cc);
-           } else {
-               what = "krb5_cc_resolve";
-               code = krb5_cc_resolve(k5context, "MEMORY:core", &cc);
-               if (code) goto Failed;
-           }
-           what = "initializing ccache";
-           code = krb5_cc_initialize(k5context, cc, princ);
-           if (code) goto Failed;
-           what = "writing Kerberos ticket file";
-           code = krb5_cc_store_cred(k5context, cc, incred);
-           if (code) goto Failed;
-           if (writeTicketFile)
-               fprintf(stderr,
-                   "Wrote ticket file to %s\n",
-                   krb5_cc_get_name(k5context, cc));
-           break;
-       Failed:
-           if (code)
-               afs_com_err(rn, code, "%s", what);
-           if (writeTicketFile) {
-               if (cc) {
-                   krb5_cc_close(k5context, cc);
-                   cc = 0;
-               }
-               continue;
-           }
-           KLOGEXIT(code);
-       }
+    for (;;writeTicketFile = 0) {
+        if (writeTicketFile) {
+            what = "getting default ccache";
+            code = krb5_cc_default(k5context, &cc);
+        } else {
+            what = "krb5_cc_resolve";
+            code = krb5_cc_resolve(k5context, "MEMORY:core", &cc);
+            if (code) goto Failed;
+        }
+        what = "initializing ccache";
+        code = krb5_cc_initialize(k5context, cc, princ);
+        if (code) goto Failed;
+        what = "writing Kerberos ticket file";
+        code = krb5_cc_store_cred(k5context, cc, incred);
+        if (code) goto Failed;
+        if (writeTicketFile)
+            fprintf(stderr,
+                    "Wrote ticket file to %s\n",
+                    krb5_cc_get_name(k5context, cc));
+        break;
+      Failed:
+        if (code)
+            afs_com_err(rn, code, "%s", what);
+        if (writeTicketFile) {
+            if (cc) {
+                krb5_cc_close(k5context, cc);
+                cc = 0;
+            }
+            continue;
+        }
+        KLOGEXIT(code);
+    }
 
-       for (service = service_temp;;service = "afs") {
-           memset(mcred, 0, sizeof *mcred);
-           mcred->client = princ;
-           code = krb5_parse_name(k5context, service, &mcred->server);
-           if (code) {
-               afs_com_err(rn, code, "Unable to parse service <%s>\n", service);
-               KLOGEXIT(code);
-           }
-           if (tofree) { free(tofree); tofree = 0; }
-           if (!(code = krb5_unparse_name(k5context, mcred->server, &outname)))
-               tofree = outname;
-           else outname = service;
-           code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred);
-           krb5_free_principal(k5context, mcred->server);
-           if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break;
+    for (service = service_temp;;service = "afs") {
+        memset(mcred, 0, sizeof *mcred);
+        mcred->client = princ;
+        code = krb5_parse_name(k5context, service, &mcred->server);
+        if (code) {
+            afs_com_err(rn, code, "Unable to parse service <%s>\n", service);
+            KLOGEXIT(code);
+        }
+        if (tofree) { free(tofree); tofree = 0; }
+        if (!(code = krb5_unparse_name(k5context, mcred->server, &outname)))
+            tofree = outname;
+        else outname = service;
+        code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred);
+        krb5_free_principal(k5context, mcred->server);
+        if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break;
 #ifdef AFS_RXK5
-           if (authtype & FORCE_RXK5) break;
+        if (authtype & FORCE_RXK5)
+            break;
 #endif
-       }
-       afscred = outcred;
     }
+    afscred = outcred;
+
     if (code) {
        afs_com_err(rn, code, "Unable to get credentials to use %s", outname);
        KLOGEXIT(code);
@@ -705,8 +575,15 @@ CommandProc(struct cmd_syndesc *as, void *arock)
        }
        atoken->startTime = afscred->times.starttime;
        atoken->endTime = afscred->times.endtime;
-       memcpy(&atoken->sessionKey, get_cred_keydata(afscred),
-           get_cred_keylen(afscred));
+       if (tkt_DeriveDesKey(get_creds_enctype(afscred),
+                            get_cred_keydata(afscred),
+                            get_cred_keylen(afscred), &atoken->sessionKey)) {
+           afs_com_err(rn, 0,
+                       "Cannot derive DES key from enctype %i of length %u",
+                       get_creds_enctype(afscred),
+                       (unsigned)get_cred_keylen(afscred));
+           KLOGEXIT(1);
+       }
        memcpy(atoken->ticket, enc_part->data,
            atoken->ticketLen = enc_part->length);
        memset(aserver, 0, sizeof *aserver);