* Used by /sbin/request-key for handling
* cifs upcall for kerberos authorization of access to share and
* cifs upcall for DFS srver name resolving (IPv4/IPv6 aware).
-* You should have keyutils installed and add following line to
-* /etc/request-key.conf file
+* You should have keyutils installed and add something like the
+* following lines to /etc/request-key.conf file:
-create cifs.spnego * * /usr/local/sbin/cifs.upcall [-v][-c] %k
-create cifs.resolver * * /usr/local/sbin/cifs.upcall [-v] %k
+create cifs.spnego * * /usr/local/sbin/cifs.upcall %k
+create dns_resolver * * /usr/local/sbin/cifs.upcall %k
* 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
#include "cifs_spnego.h"
-const char *CIFSSPNEGO_VERSION = "1.1";
+const char *CIFSSPNEGO_VERSION = "1.2";
static const char *prog = "cifs.upcall";
typedef enum _secType {
KRB5,
tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
/* and wrap that in a shiny SPNEGO wrapper */
- *secblob = gen_negTokenInit(OID_KERBEROS5, tkt_wrapped);
+ *secblob = gen_negTokenInit(oid, tkt_wrapped);
data_blob_free(&tkt_wrapped);
data_blob_free(&tkt);
if (strncmp(tkn + 4, "krb5", 4) == 0) {
retval |= DKD_HAVE_SEC;
*sec = KRB5;
+ } else if (strncmp(tkn + 4, "mskrb5", 6) == 0) {
+ retval |= DKD_HAVE_SEC;
+ *sec = MS_KRB5;
}
} else if (strncmp(tkn, "uid=", 4) == 0) {
errno = 0;
}
void
-usage(const char *prog)
+usage(void)
{
syslog(LOG_WARNING, "Usage: %s [-c] [-v] key_serial", prog);
fprintf(stderr, "Usage: %s [-c] [-v] key_serial\n", prog);
DATA_BLOB secblob = data_blob_null;
DATA_BLOB sess_key = data_blob_null;
secType_t sectype;
- key_serial_t key;
+ key_serial_t key = 0;
size_t datalen;
long rc = 1;
uid_t uid;
int kernel_upcall_version;
int c, use_cifs_service_prefix = 0;
- char *buf, *hostname = NULL;
+ char *buf, *oid, *hostname = NULL;
openlog(prog, 0, LOG_DAEMON);
goto out;
}
default:{
- syslog(LOG_WARNING, "unknow option: %c", c);
+ syslog(LOG_WARNING, "unknown option: %c", c);
goto out;
}
}
/* is there a key? */
if (argc <= optind) {
- usage(prog);
+ usage();
goto out;
}
errno = 0;
key = strtol(argv[optind], NULL, 10);
if (errno != 0) {
+ key = 0;
syslog(LOG_WARNING, "Invalid key format: %s", strerror(errno));
goto out;
}
goto out;
}
- if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver")-1) == 0) {
+ if ((strncmp(buf, "cifs.resolver", sizeof("cifs.resolver")-1) == 0) ||
+ (strncmp(buf, "dns_resolver", sizeof("dns_resolver")-1) == 0)) {
rc = cifs_resolver(key, buf);
goto out;
}
// do mech specific authorization
switch (sectype) {
+ case MS_KRB5:
case KRB5:{
char *princ;
size_t len;
}
strlcpy(princ + 5, hostname, len - 5);
- rc = handle_krb5_mech(OID_KERBEROS5, princ,
- &secblob, &sess_key);
+ if (sectype == MS_KRB5)
+ oid = OID_KERBEROS5_OLD;
+ else
+ oid = OID_KERBEROS5;
+
+ rc = handle_krb5_mech(oid, princ, &secblob, &sess_key);
SAFE_FREE(princ);
break;
}
/* BB: maybe we need use timeout for key: for example no more then
* ticket lifietime? */
/* keyctl_set_timeout( key, 60); */
- out:
+out:
+ /*
+ * on error, negatively instantiate the key ourselves so that we can
+ * make sure the kernel doesn't hang it off of a searchable keyring
+ * and interfere with the next attempt to instantiate the key.
+ */
+ if (rc != 0 && key == 0)
+ keyctl_negate(key, 1, KEY_REQKEY_DEFL_DEFAULT);
data_blob_free(&secblob);
data_blob_free(&sess_key);
SAFE_FREE(hostname);