summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbfs
diff options
context:
space:
mode:
authorGordon Ross <Gordon.Ross@Sun.COM>2010-04-12 18:46:28 -0400
committerGordon Ross <Gordon.Ross@Sun.COM>2010-04-12 18:46:28 -0400
commit15359501f7d4b9abebd7b7bf6efd5982a8e7eb27 (patch)
treed9163de03299c4d225afcbec58ee9b2f7615ce6f /usr/src/lib/libsmbfs
parent046cfe5c17cdf5694e6d0d26efdc0e95ad2a1fbc (diff)
downloadillumos-joyent-15359501f7d4b9abebd7b7bf6efd5982a8e7eb27.tar.gz
6935517 NTLMSSP Type 3 message header is missing two fields
6936620 should preserve the username case in session setup 6939738 Need a way to specify authentication types for testing 6939914 avoid fragmenting session setup 6939297 krb5 AP_REQ checksum is incorrect 6939356 system/filesystem-smb lacks dependency on system/library/iconv/utf-8
Diffstat (limited to 'usr/src/lib/libsmbfs')
-rw-r--r--usr/src/lib/libsmbfs/smb/ctx.c110
-rw-r--r--usr/src/lib/libsmbfs/smb/krb5ssp.c35
-rw-r--r--usr/src/lib/libsmbfs/smb/mbuf.c9
-rw-r--r--usr/src/lib/libsmbfs/smb/nb_ssn.c44
-rw-r--r--usr/src/lib/libsmbfs/smb/ntlm.c19
-rw-r--r--usr/src/lib/libsmbfs/smb/ntlmssp.c50
-rw-r--r--usr/src/lib/libsmbfs/smb/ssnsetup.c5
7 files changed, 170 insertions, 102 deletions
diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c
index d29ec7bf0b..be97571321 100644
--- a/usr/src/lib/libsmbfs/smb/ctx.c
+++ b/usr/src/lib/libsmbfs/smb/ctx.c
@@ -33,8 +33,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/param.h>
@@ -77,6 +76,10 @@
#define TRUE 1
#endif
+struct nv {
+ char *name;
+ int value;
+};
/* These two may be set by commands. */
int smb_debug, smb_verbose;
@@ -485,7 +488,6 @@ smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
const char *p = unc;
char *p1, *colon;
char tmp[1024];
- char tmp2[1024];
int error;
/*
@@ -512,7 +514,6 @@ smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
error = EINVAL;
goto out;
}
- nls_str_upper(tmp, tmp);
error = smb_ctx_setdomain(ctx, unpercent(tmp), TRUE);
if (error)
goto out;
@@ -564,17 +565,6 @@ smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
}
/*
- * It's safe to uppercase this string, which
- * consists of ascii characters that should
- * be uppercased, %s, and ascii characters representing
- * hex digits 0-9 and A-F (already uppercased, and
- * if not uppercased they need to be). However,
- * it is NOT safe to uppercase after it has been
- * "unpercent" converted, below!
- */
- nls_str_upper(tmp2, tmp);
-
- /*
* Save ct_fullserver without case conversion.
*/
if (strchr(tmp, '%'))
@@ -683,11 +673,9 @@ smb_ctx_setfullserver(struct smb_ctx *ctx, const char *name)
return (0);
}
-/* this routine does not uppercase the server name */
int
smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
{
- /* don't uppercase the server name */
strlcpy(ctx->ct_srvname, name,
sizeof (ctx->ct_srvname));
return (0);
@@ -710,7 +698,6 @@ smb_ctx_setuser(struct smb_ctx *ctx, const char *name, int from_cmd)
if (!from_cmd && (ctx->ct_flags & SMBCF_CMD_USR))
return (0);
- /* don't uppercase the username, just copy it. */
strlcpy(ctx->ct_user, name,
sizeof (ctx->ct_user));
@@ -722,10 +709,6 @@ smb_ctx_setuser(struct smb_ctx *ctx, const char *name, int from_cmd)
}
/*
- * Never uppercase the workgroup
- * name here, because it might come
- * from a Windows codepage encoding.
- *
* Don't overwrite a domain name from the
* command line with one from anywhere else.
* See smb_ctx_init() for notes about this.
@@ -907,6 +890,66 @@ smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
}
/*
+ * Suport a securty options arg, i.e. -S noext,lm,ntlm
+ * for testing various type of authenticators.
+ */
+static struct nv
+sectype_table[] = {
+ /* noext - handled below */
+ { "anon", SMB_AT_ANON },
+ { "lm", SMB_AT_LM1 },
+ { "ntlm", SMB_AT_NTLM1 },
+ { "ntlm2", SMB_AT_NTLM2 },
+ { "krb5", SMB_AT_KRB5 },
+ { NULL, 0 },
+};
+int
+smb_parse_secopts(struct smb_ctx *ctx, const char *arg)
+{
+ const char *sep = ":;,";
+ const char *p = arg;
+ struct nv *nv;
+ int nlen, tlen;
+ int authflags = 0;
+
+ for (;;) {
+ /* skip separators */
+ tlen = strspn(p, sep);
+ p += tlen;
+
+ nlen = strcspn(p, sep);
+ if (nlen == 0)
+ break;
+
+ if (nlen == 5 && 0 == strncmp(p, "noext", nlen)) {
+ /* Don't offer extended security. */
+ ctx->ct_vopt &= ~SMBVOPT_EXT_SEC;
+ p += nlen;
+ continue;
+ }
+
+ /* This is rarely called, so not optimized. */
+ for (nv = sectype_table; nv->name; nv++) {
+ tlen = strlen(nv->name);
+ if (tlen == nlen && 0 == strncmp(p, nv->name, tlen))
+ break;
+ }
+ if (nv->name == NULL) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "%s: invalid security options"), 0, p);
+ return (EINVAL);
+ }
+ authflags |= nv->value;
+ p += nlen;
+ }
+
+ if (authflags)
+ ctx->ct_authflags = authflags;
+
+ return (0);
+}
+
+/*
* Commands use this with getopt. See:
* STDPARAM_OPT, STDPARAM_ARGS
* Called after smb_ctx_readrc().
@@ -947,12 +990,15 @@ smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg)
case 'R':
/* retry count - ignored */
break;
+ case 'S':
+ /* Security options (undocumented, just for tests) */
+ error = smb_parse_secopts(ctx, arg);
+ break;
case 'T':
/* timeout - ignored */
break;
case 'D': /* domain */
case 'W': /* workgroup (legacy alias) */
- nls_str_upper(tmp, arg);
error = smb_ctx_setdomain(ctx, tmp, TRUE);
break;
}
@@ -996,6 +1042,9 @@ smb_ctx_resolve(struct smb_ctx *ctx)
uint_t i;
#endif
+ if (smb_debug)
+ dump_ctx("before smb_ctx_resolve", ctx);
+
ctx->ct_flags &= ~SMBCF_RESOLVED;
if (ctx->ct_fullserver == NULL) {
@@ -1077,12 +1126,6 @@ smb_ctx_resolve(struct smb_ctx *ctx)
if (ctx->ct_password[0] == '\0')
(void) smb_get_keychain(ctx);
/*
- * If we're doing p/w based auth,
- * that means not using Kerberos.
- */
- if (ctx->ct_password[0] != '\0')
- ctx->ct_authflags &= ~SMB_AT_KRB5;
- /*
* Mask out disallowed auth types.
*/
ctx->ct_authflags &= ctx->ct_minauth;
@@ -1327,15 +1370,12 @@ smb_ctx_get_ssnkey(struct smb_ctx *ctx, uchar_t *key, size_t len)
return (0);
}
-
/*
* RC file parsing stuff
*/
-struct nv {
- char *name;
- int value;
-} minauth_table[] = {
+static struct nv
+minauth_table[] = {
/* Allowed auth. types */
{ "kerberos", SMB_AT_KRB5 },
{ "ntlmv2", SMB_AT_KRB5|SMB_AT_NTLM2 },
@@ -1432,7 +1472,6 @@ smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
*/
rc_getstringptr(smb_rc, sname, "workgroup", &p);
if (p) {
- nls_str_upper(p, p);
error = smb_ctx_setdomain(ctx, p, 0);
if (error)
smb_error(dgettext(TEXT_DOMAIN,
@@ -1441,7 +1480,6 @@ smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
}
rc_getstringptr(smb_rc, sname, "domain", &p);
if (p) {
- nls_str_upper(p, p);
error = smb_ctx_setdomain(ctx, p, 0);
if (error)
smb_error(dgettext(TEXT_DOMAIN,
diff --git a/usr/src/lib/libsmbfs/smb/krb5ssp.c b/usr/src/lib/libsmbfs/smb/krb5ssp.c
index 190a755499..208ec6d0a4 100644
--- a/usr/src/lib/libsmbfs/smb/krb5ssp.c
+++ b/usr/src/lib/libsmbfs/smb/krb5ssp.c
@@ -31,8 +31,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -75,6 +74,11 @@
#include <kerberosv5/krb5.h>
#include <kerberosv5/com_err.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/mechs/krb5/include/auth_con.h>
+
+/* RFC 4121 checksum type ID. */
+#define CKSUM_TYPE_RFC4121 0x8003
/* RFC 1964 token ID codes */
#define KRB_AP_REQ 1
@@ -179,8 +183,28 @@ krb5ssp_get_tkt(krb5ssp_state_t *ss, char *server,
goto out;
}
- /* Override the krb5 library default. */
- indata.data = "";
+ /* Get ss_auth now so we can set req_chsumtype. */
+ kerr = krb5_auth_con_init(kctx, &ss->ss_auth);
+ if (kerr != 0) {
+ fn = "krb5_auth_con_init";
+ goto out;
+ }
+ /* Missing krb5_auth_con_set_req_cksumtype(), so inline. */
+ ss->ss_auth->req_cksumtype = CKSUM_TYPE_RFC4121;
+
+ /*
+ * Build an RFC 4121 "checksum" with NULL channel bindings,
+ * like make_gss_checksum(). Numbers here from the RFC.
+ */
+ indata.length = 24;
+ if ((indata.data = calloc(1, indata.length)) == NULL) {
+ kerr = ENOMEM;
+ fn = "malloc checksum";
+ goto out;
+ }
+ indata.data[0] = 16; /* length of "Bnd" field. */
+ indata.data[20] = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;
+ /* Done building the "checksum". */
kerr = krb5_mk_req(kctx, &ss->ss_auth, rq_opts, "cifs", server,
&indata, kcc, &outdata);
@@ -210,6 +234,9 @@ out:
if (outdata.data)
krb5_free_data_contents(kctx, &outdata);
+ if (indata.data)
+ free(indata.data);
+
/* Free kctx in krb5ssp_destroy */
return (kerr);
}
diff --git a/usr/src/lib/libsmbfs/smb/mbuf.c b/usr/src/lib/libsmbfs/smb/mbuf.c
index 86710f3f94..79da0209c1 100644
--- a/usr/src/lib/libsmbfs/smb/mbuf.c
+++ b/usr/src/lib/libsmbfs/smb/mbuf.c
@@ -33,8 +33,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -121,14 +120,15 @@ m_lineup(struct mbuf *m0, struct mbuf **mpp)
{
struct mbuf *nm, *m;
char *dp;
- size_t len;
+ size_t len, totlen;
int error;
if (m0->m_next == NULL) {
*mpp = m0;
return (0);
}
- if ((error = m_get(m_totlen(m0), &nm)) != 0)
+ totlen = m_totlen(m0);
+ if ((error = m_get(totlen, &nm)) != 0)
return (error);
dp = mtod(nm, char *);
while (m0) {
@@ -139,6 +139,7 @@ m_lineup(struct mbuf *m0, struct mbuf **mpp)
m_free(m0);
m0 = m;
}
+ nm->m_len = totlen;
*mpp = nm;
return (0);
}
diff --git a/usr/src/lib/libsmbfs/smb/nb_ssn.c b/usr/src/lib/libsmbfs/smb/nb_ssn.c
index 44d5a48120..319e250296 100644
--- a/usr/src/lib/libsmbfs/smb/nb_ssn.c
+++ b/usr/src/lib/libsmbfs/smb/nb_ssn.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -70,18 +69,17 @@ static int
nb_ssn_send(struct smb_ctx *ctx, struct mbdata *mbp,
int mtype, int mlen)
{
- mbuf_t *m = mbp->mb_top;
- int fd = ctx->ct_tran_fd;
- int err, flags;
+ mbuf_t *m;
uint32_t hdr, hdrbuf;
+ int err;
+ m = mbp->mb_top;
if (m == NULL)
return (EINVAL);
/*
* Prepend the NetBIOS header.
- * Using mbuf trickery to ensure it's
- * not separated from the body.
+ * Our mbufs leave space for this.
*/
hdr = (mtype << 24) | mlen;
hdrbuf = htonl(hdr);
@@ -89,19 +87,27 @@ nb_ssn_send(struct smb_ctx *ctx, struct mbdata *mbp,
m->m_len += 4;
bcopy(&hdrbuf, m->m_data, 4);
- /* Send it. */
- while (m) {
- flags = (m->m_next) ? T_MORE : T_PUSH;
- if (t_snd(fd, m->m_data, m->m_len, flags) < 0) {
- if (t_errno == TSYSERR)
- err = errno;
- else
- err = EPROTO;
- DPRINT("t_snd: t_errno %d, err %d", t_errno, err);
- return (err);
- }
- m = m->m_next;
+ /*
+ * Get contiguous data (so TCP won't fragment)
+ * Note: replaces mb_top.
+ */
+ err = m_lineup(mbp->mb_top, &mbp->mb_top);
+ if (err)
+ return (err);
+ m = mbp->mb_top;
+
+ /*
+ * Send it.
+ */
+ if (t_snd(ctx->ct_tran_fd, m->m_data, m->m_len, 0) < 0) {
+ if (t_errno == TSYSERR)
+ err = errno;
+ else
+ err = EPROTO;
+ DPRINT("t_snd: t_errno %d, err %d", t_errno, err);
+ return (err);
}
+
return (0);
}
diff --git a/usr/src/lib/libsmbfs/smb/ntlm.c b/usr/src/lib/libsmbfs/smb/ntlm.c
index ffd9ff3d41..bee189561e 100644
--- a/usr/src/lib/libsmbfs/smb/ntlm.c
+++ b/usr/src/lib/libsmbfs/smb/ntlm.c
@@ -33,8 +33,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -407,8 +406,7 @@ ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
{
uchar_t *lmresp, *ntresp;
int err;
- char *ucdom = NULL; /* user's domain */
- char *ucuser = NULL; /* account name */
+ char *ucuser = NULL; /* upper-case user name */
uchar_t v2hash[NTLM_HASH_SZ];
struct mbuf *tim = ti_mbp->mb_top;
@@ -420,20 +418,20 @@ ntlm_put_v2_responses(struct smb_ctx *ctx, struct mbdata *ti_mbp,
/*
* Convert the user name to upper-case, as
* that's what's used when computing LMv2
- * and NTLMv2 responses. Also the domain.
+ * and NTLMv2 responses. Note that the
+ * domain name is NOT upper-cased!
*/
- ucdom = utf8_str_toupper(ctx->ct_domain);
ucuser = utf8_str_toupper(ctx->ct_user);
- if (ucdom == NULL || ucuser == NULL) {
+ if (ucuser == NULL) {
err = ENOMEM;
goto out;
}
/*
- * Compute the NTLMv2 hash (see above)
- * Needs upper-case user, domain.
+ * Compute the NTLMv2 hash
*/
- err = ntlm_v2_hash(v2hash, ctx->ct_nthash, ucuser, ucdom);
+ err = ntlm_v2_hash(v2hash, ctx->ct_nthash,
+ ucuser, ctx->ct_domain);
if (err)
goto out;
@@ -483,7 +481,6 @@ out:
mb_done(lm_mbp);
mb_done(nt_mbp);
}
- free(ucdom);
free(ucuser);
return (err);
diff --git a/usr/src/lib/libsmbfs/smb/ntlmssp.c b/usr/src/lib/libsmbfs/smb/ntlmssp.c
index 535777b187..687d91b355 100644
--- a/usr/src/lib/libsmbfs/smb/ntlmssp.c
+++ b/usr/src/lib/libsmbfs/smb/ntlmssp.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -394,34 +393,26 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
struct sec_buf h_domain;
struct sec_buf h_user;
struct sec_buf h_wksta;
+ struct sec_buf h_ssn_key;
+ uint32_t h_flags;
} hdr;
- struct mbdata lm_mbc, nt_mbc, ti_mbc;
- struct mbdata mb2; /* 2nd part */
+ struct mbdata lm_mbc; /* LM response */
+ struct mbdata nt_mbc; /* NT response */
+ struct mbdata ti_mbc; /* target info */
+ struct mbdata mb2; /* payload */
int err, uc;
- char *ucdom = NULL; /* user's domain */
- char *ucuser = NULL; /* user name */
- char *ucwksta = NULL; /* workstation */
struct smb_ctx *ctx = sp->smb_ctx;
ntlmssp_state_t *ssp_st = sp->sp_private;
+ bzero(&hdr, sizeof (hdr));
bzero(&lm_mbc, sizeof (lm_mbc));
bzero(&nt_mbc, sizeof (nt_mbc));
bzero(&ti_mbc, sizeof (ti_mbc));
bzero(&mb2, sizeof (mb2));
/*
- * Convert the user name to upper-case, as that's what's
- * used when computing LMv2 and NTLMv2 responses. Also
- * domain, workstation
+ * Fill in the NTLMSSP header, etc.
*/
- ucdom = utf8_str_toupper(ctx->ct_domain);
- ucuser = utf8_str_toupper(ctx->ct_user);
- ucwksta = utf8_str_toupper(ctx->ct_locname);
- if (ucdom == NULL || ucuser == NULL || ucwksta == NULL) {
- err = ENOMEM;
- goto out;
- }
-
if ((err = mb_init(&mb2)) != 0)
goto out;
mb2.mb_count = sizeof (hdr);
@@ -429,6 +420,7 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
bcopy(ntlmssp_id, &hdr.h_id, ID_SZ);
hdr.h_type = 3; /* Type 3 */
+ hdr.h_flags = ssp_st->ss_flags;
/*
* Put the LMv2,NTLMv2 responses, or
@@ -461,17 +453,25 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
/*
* Put the "target" (domain), user, workstation
*/
- err = mb_put_sb_string(&mb2, &hdr.h_domain, ucdom, uc);
+ err = mb_put_sb_string(&mb2, &hdr.h_domain, ctx->ct_domain, uc);
if (err)
goto out;
- err = mb_put_sb_string(&mb2, &hdr.h_user, ucuser, uc);
+ err = mb_put_sb_string(&mb2, &hdr.h_user, ctx->ct_user, uc);
if (err)
goto out;
- err = mb_put_sb_string(&mb2, &hdr.h_wksta, ucwksta, uc);
+ err = mb_put_sb_string(&mb2, &hdr.h_wksta, ctx->ct_locname, uc);
if (err)
goto out;
/*
+ * Put the "Random Session Key". We don't set
+ * NTLMSSP_NEGOTIATE_KEY_EXCH, so it's empty.
+ * (In-line mb_put_sb_data here.)
+ */
+ hdr.h_ssn_key.sb_maxlen = hdr.h_ssn_key.sb_length = 0;
+ hdr.h_ssn_key.sb_offset = mb2.mb_count;
+
+ /*
* Marshal the header (in LE order)
* then concatenate the 2nd part.
*/
@@ -485,17 +485,17 @@ ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb)
(void) mb_put_sb_hdr(out_mb, &hdr.h_user);
(void) mb_put_sb_hdr(out_mb, &hdr.h_wksta);
+ (void) mb_put_sb_hdr(out_mb, &hdr.h_ssn_key);
+ (void) mb_put_uint32le(out_mb, hdr.h_flags);
+
err = mb_put_mbuf(out_mb, mb2.mb_top);
mb2.mb_top = NULL; /* consumed */
out:
- free(ucdom);
- free(ucuser);
- free(ucwksta);
-
mb_done(&mb2);
mb_done(&lm_mbc);
mb_done(&nt_mbc);
+ mb_done(&ti_mbc);
return (err);
}
diff --git a/usr/src/lib/libsmbfs/smb/ssnsetup.c b/usr/src/lib/libsmbfs/smb/ssnsetup.c
index 712a71f34c..c8234c8040 100644
--- a/usr/src/lib/libsmbfs/smb/ssnsetup.c
+++ b/usr/src/lib/libsmbfs/smb/ssnsetup.c
@@ -31,8 +31,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -287,7 +286,7 @@ smb_ssnsetup_spnego(struct smb_ctx *ctx, struct mbdata *hint_mb)
break; /* normal loop termination */
if (ntstatus != STATUS_MORE_PROCESSING_REQUIRED) {
err = EAUTH;
- break;
+ goto out;
}
/* middle calls get both in, out */