#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;
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;
+ const char *oid;
openlog(prog, 0, LOG_DAEMON);
errno = 0;
key = strtol(argv[optind], NULL, 10);
if (errno != 0) {
+ key = 0;
syslog(LOG_WARNING, "Invalid key format: %s", strerror(errno));
goto out;
}
}
SAFE_FREE(buf);
- if (kernel_upcall_version != CIFS_SPNEGO_UPCALL_VERSION) {
+ if (kernel_upcall_version > CIFS_SPNEGO_UPCALL_VERSION) {
syslog(LOG_WARNING,
"incompatible kernel upcall version: 0x%x",
kernel_upcall_version);
// 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;
}
rc = 1;
goto out;
}
- keydata->version = CIFS_SPNEGO_UPCALL_VERSION;
+ keydata->version = kernel_upcall_version;
keydata->flags = 0;
keydata->sesskey_len = sess_key.length;
keydata->secblob_len = secblob.length;
/* 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);