summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-05-20 22:49:24 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2018-05-20 22:49:24 +0200
commit6e19d19285dddcd3c8f2a6b031fc0f0324b3e48b (patch)
treeed9d6c1d7cf83555a498b01563a24284cb20b2d5
parent40f6e00b9c4b0f5bdca1cc7caf27af23a6b10786 (diff)
separate MSCHAP(v2) and NTLM(v2) authentication
due to linux omiting the final Z(4) in the NTLMv2 reply, and the need for the windom for LMv2 authentication, here is a new AuthNTLM ticket request now with length and dom fields.
-rw-r--r--sys/include/auth.h3
-rw-r--r--sys/include/authsrv.h12
-rw-r--r--sys/src/cmd/auth/factotum/chap.c81
-rw-r--r--sys/src/cmd/auth/factotum/dat.h2
-rw-r--r--sys/src/cmd/auth/factotum/fs.c3
-rw-r--r--sys/src/cmd/cifs/auth.c6
-rw-r--r--sys/src/cmd/ip/cifsd/smb.c3
-rw-r--r--sys/src/libauth/auth_challenge.c9
8 files changed, 92 insertions, 27 deletions
diff --git a/sys/include/auth.h b/sys/include/auth.h
index d7f58035e..8b350a64c 100644
--- a/sys/include/auth.h
+++ b/sys/include/auth.h
@@ -53,6 +53,7 @@ struct AuthInfo
struct Chalstate
{
char *user;
+ char *dom;
char chal[MAXCHLEN];
int nchal;
void *resp;
@@ -71,7 +72,7 @@ struct Chapreply /* for protocol "chap" */
char resp[MD5LEN];
};
-struct MSchapreply /* for protocol "mschap" */
+struct MSchapreply /* for protocol "mschap" and "ntlm" */
{
char LMresp[24]; /* Lan Manager response */
char NTresp[24]; /* NT response */
diff --git a/sys/include/authsrv.h b/sys/include/authsrv.h
index 5c0b368e7..8fb2d08df 100644
--- a/sys/include/authsrv.h
+++ b/sys/include/authsrv.h
@@ -11,6 +11,7 @@ typedef struct Nvrsafe Nvrsafe;
typedef struct Passwordreq Passwordreq;
typedef struct OChapreply OChapreply;
typedef struct OMSchapreply OMSchapreply;
+typedef struct NTLMreply NTLMreply;
typedef struct Authkey Authkey;
@@ -62,6 +63,7 @@ enum
AuthVNC=14, /* VNC server login (deprecated) */
AuthPAK=19, /* authenticated diffie hellman key agreement */
AuthMSchapv2=21,/* MS chap v2 authentication for ppp */
+ AuthNTLM=22, /* NTLM authentication for cifs */
AuthTs=64, /* ticket encrypted with server's key */
AuthTc, /* ticket encrypted with client's key */
AuthAs, /* server generated authenticator */
@@ -127,6 +129,16 @@ struct OMSchapreply
};
#define OMSCHAPREPLYLEN (ANAMELEN+24+24)
+struct NTLMreply
+{
+ uchar len[2]; /* size of structure (lsb first) */
+ char uid[ANAMELEN];
+ char dom[DOMLEN];
+ char LMresp[24]; /* Lan Manager response */
+ char NTresp[24]; /* NT response (variable length) */
+};
+#define NTLMREPLYLEN (2+ANAMELEN+DOMLEN+24+24)
+
struct Authkey
{
char des[DESKEYLEN]; /* DES key from password */
diff --git a/sys/src/cmd/auth/factotum/chap.c b/sys/src/cmd/auth/factotum/chap.c
index 56ad476c3..ae8cd6097 100644
--- a/sys/src/cmd/auth/factotum/chap.c
+++ b/sys/src/cmd/auth/factotum/chap.c
@@ -10,6 +10,7 @@
* Server protocol:
* read challenge: 8 bytes binary (or 16 bytes for mschapv2)
* write user: utf8
+ * write dom: utf8 (ntlm)
* write response: Chapreply or MSchapreply structure
* ... retry another user
*/
@@ -36,7 +37,7 @@ static int dochal(State *s);
static int doreply(State *s, uchar *reply, int nreply);
static int dochap(char *passwd, int id, char chal[ChapChallen], uchar *resp, int resplen);
static int domschap(char *passwd, uchar chal[MSchallen], uchar *resp, int resplen);
-static int domschap2(char *passwd, char *user, char *dom, uchar chal[MSchallen], uchar *resp, int resplen);
+static int dontlmv2(char *passwd, char *user, char *dom, uchar chal[MSchallen], uchar *resp, int resplen);
static void nthash(uchar hash[MShashlen], char *passwd);
struct State
@@ -53,6 +54,7 @@ struct State
uchar resp[4096];
char err[ERRMAX];
char user[64];
+ char dom[DOMLEN];
uchar secret[16+20]; /* for mschap: MPPE Master secret + authenticator (v2) */
int nsecret;
};
@@ -64,6 +66,7 @@ enum
SHaveChal,
SNeedUser,
+ SNeedDom,
SNeedResp,
Maxphase
@@ -76,6 +79,7 @@ static char *phasenames[Maxphase] =
[SHaveChal] "SHaveChal",
[SNeedUser] "SNeedUser",
+[SNeedDom] "SNeedDom",
[SNeedResp] "SNeedResp",
};
@@ -98,14 +102,15 @@ chapinit(Proto *p, Fsstate *fss)
if(p == &mschapv2) {
s->nchal = MSchallenv2;
s->astype = AuthMSchapv2;
+ } else if(p == &mschap){
+ s->nchal = MSchallen;
+ s->astype = AuthMSchap;
+ } else if(p == &ntlm || p == &ntlmv2){
+ s->nchal = MSchallen;
+ s->astype = AuthNTLM;
} else {
- if(p == &mschap || p == &mschap2){
- s->nchal = MSchallen;
- s->astype = AuthMSchap;
- }else {
- s->nchal = ChapChallen;
- s->astype = AuthChap;
- }
+ s->nchal = ChapChallen;
+ s->astype = AuthChap;
}
if(iscli)
fss->phase = CNeedChal;
@@ -150,6 +155,7 @@ chapwrite(Fsstate *fss, void *va, uint n)
MSchapreply *mcr;
OChapreply *ocr;
OMSchapreply *omcr;
+ NTLMreply *ntcr;
uchar pchal[MSchallenv2];
uchar digest[SHA1dlen];
uchar reply[4096];
@@ -177,20 +183,25 @@ chapwrite(Fsstate *fss, void *va, uint n)
memset(s->resp, 0, sizeof(s->resp));
setattrs(fss->attr, k->attr);
switch(s->astype){
- case AuthMSchap:
+ case AuthNTLM:
if(n < MSchallen)
break;
- if(fss->proto == &mschap2){
+ if(fss->proto == &ntlmv2){
user = _strfindattr(fss->attr, "user");
if(user == nil)
break;
dom = _strfindattr(fss->attr, "windom");
if(dom == nil)
dom = "";
- s->nresp = domschap2(pass, user, dom, (uchar*)a, s->resp, sizeof(s->resp));
+ s->nresp = dontlmv2(pass, user, dom, (uchar*)a, s->resp, sizeof(s->resp));
} else {
s->nresp = domschap(pass, (uchar*)a, s->resp, sizeof(s->resp));
}
+ break;
+ case AuthMSchap:
+ if(n < MSchallen)
+ break;
+ s->nresp = domschap(pass, (uchar*)a, s->resp, sizeof(s->resp));
nthash(digest, pass);
md4(digest, 16, digest, nil);
ds = sha1(digest, 16, nil, nil);
@@ -253,6 +264,14 @@ chapwrite(Fsstate *fss, void *va, uint n)
return failure(fss, "user name too long");
memmove(s->user, va, n);
s->user[n] = '\0';
+ fss->phase = (s->astype == AuthNTLM)? SNeedDom: SNeedResp;
+ return RpcOk;
+
+ case SNeedDom:
+ if(n >= sizeof s->dom)
+ return failure(fss, "domain name too long");
+ memmove(s->dom, va, n);
+ s->dom[n] = '\0';
fss->phase = SNeedResp;
return RpcOk;
@@ -275,15 +294,29 @@ chapwrite(Fsstate *fss, void *va, uint n)
case AuthMSchapv2:
if(n < MSchapreplylen)
return failure(fss, "did not get MSchapreply");
- if(n > sizeof(reply)+MSchapreplylen-OMSCHAPREPLYLEN)
- return failure(fss, "MSchapreply too long");
mcr = (MSchapreply*)va;
- nreply = n+OMSCHAPREPLYLEN-MSchapreplylen;
+ nreply = OMSCHAPREPLYLEN;
memset(reply, 0, nreply);
omcr = (OMSchapreply*)reply;
strecpy(omcr->uid, omcr->uid+sizeof(omcr->uid), s->user);
memmove(omcr->LMresp, mcr->LMresp, sizeof(omcr->LMresp));
- memmove(omcr->NTresp, mcr->NTresp, n+sizeof(mcr->NTresp)-MSchapreplylen);
+ memmove(omcr->NTresp, mcr->NTresp, sizeof(mcr->NTresp));
+ break;
+ case AuthNTLM:
+ if(n < MSchapreplylen)
+ return failure(fss, "did not get MSchapreply");
+ if(n > sizeof(reply)+MSchapreplylen-NTLMREPLYLEN)
+ return failure(fss, "MSchapreply too long");
+ mcr = (MSchapreply*)va;
+ nreply = n+NTLMREPLYLEN-MSchapreplylen;
+ memset(reply, 0, nreply);
+ ntcr = (NTLMreply*)reply;
+ ntcr->len[0] = nreply;
+ ntcr->len[1] = nreply>>8;
+ strecpy(ntcr->uid, ntcr->uid+sizeof(ntcr->uid), s->user);
+ strecpy(ntcr->dom, ntcr->dom+sizeof(ntcr->dom), s->dom);
+ memmove(ntcr->LMresp, mcr->LMresp, sizeof(ntcr->LMresp));
+ memmove(ntcr->NTresp, mcr->NTresp, n+sizeof(mcr->NTresp)-MSchapreplylen);
break;
}
if(doreply(s, reply, nreply) < 0){
@@ -402,12 +435,12 @@ doreply(State *s, uchar *reply, int nreply)
werrstr(Easproto);
return -1;
}
- s->key->successes++;
if(a.num != AuthAc
|| tsmemcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0){
werrstr(Easproto);
return -1;
}
+ s->key->successes++;
s->nsecret = 0;
if(s->t.form != 0){
if(s->astype == AuthMSchap || s->astype == AuthMSchapv2){
@@ -457,8 +490,18 @@ Proto mschapv2 = {
.keyprompt= "user? !password?"
};
-Proto mschap2 = {
-.name= "mschap2", /* really NTLMv2 */
+Proto ntlm = {
+.name= "ntlm",
+.init= chapinit,
+.write= chapwrite,
+.read= chapread,
+.close= chapclose,
+.addkey= replacekey,
+.keyprompt= "user? !password?"
+};
+
+Proto ntlmv2 = {
+.name= "ntlmv2",
.init= chapinit,
.write= chapwrite,
.read= chapread,
@@ -582,7 +625,7 @@ domschap(char *passwd, uchar chal[MSchallen], uchar *resp, int resplen)
}
static int
-domschap2(char *passwd, char *user, char *dom, uchar chal[MSchallen], uchar *resp, int resplen)
+dontlmv2(char *passwd, char *user, char *dom, uchar chal[MSchallen], uchar *resp, int resplen)
{
uchar hash[MShashlen], *p, *e;
MSchapreply *r;
diff --git a/sys/src/cmd/auth/factotum/dat.h b/sys/src/cmd/auth/factotum/dat.h
index 19893aa6e..d51bf919c 100644
--- a/sys/src/cmd/auth/factotum/dat.h
+++ b/sys/src/cmd/auth/factotum/dat.h
@@ -221,7 +221,7 @@ void writehostowner(char*);
/* protocols */
extern Proto apop, cram; /* apop.c */
extern Proto p9any, p9sk1, dp9ik; /* p9sk.c */
-extern Proto chap, mschap, mschapv2, mschap2; /* chap.c */
+extern Proto chap, mschap, mschapv2, ntlm, ntlmv2; /* chap.c */
extern Proto p9cr, vnc; /* p9cr.c */
extern Proto pass; /* pass.c */
extern Proto rsa; /* rsa.c */
diff --git a/sys/src/cmd/auth/factotum/fs.c b/sys/src/cmd/auth/factotum/fs.c
index 13e04ce22..3756f9a31 100644
--- a/sys/src/cmd/auth/factotum/fs.c
+++ b/sys/src/cmd/auth/factotum/fs.c
@@ -32,7 +32,8 @@ prototab[] =
&httpdigest,
&mschap,
&mschapv2,
- &mschap2,
+ &ntlm,
+ &ntlmv2,
&p9any,
&p9cr,
&p9sk1,
diff --git a/sys/src/cmd/cifs/auth.c b/sys/src/cmd/cifs/auth.c
index cc334889a..ce501b808 100644
--- a/sys/src/cmd/cifs/auth.c
+++ b/sys/src/cmd/cifs/auth.c
@@ -78,8 +78,6 @@ auth_proto(char *proto, char *windom, char *keyp, uchar *chal, int len)
mcr = (MSchapreply*)resp;
nresp = sizeof(resp);
- if(strcmp(proto, "mschap") == 0)
- nresp = sizeof(*mcr); /* backwards compatibility with old factotum */
nresp = auth_respond(chal, len, user, sizeof user, resp, nresp,
auth_getkey, "proto=%s role=client service=cifs windom=%s %s",
proto, windom, keyp);
@@ -109,7 +107,7 @@ auth_proto(char *proto, char *windom, char *keyp, uchar *chal, int len)
static Auth *
auth_lm_and_ntlm(char *windom, char *keyp, uchar *chal, int len)
{
- return auth_proto("mschap", windom, keyp, chal, len);
+ return auth_proto("ntlm", windom, keyp, chal, len);
}
/*
@@ -136,7 +134,7 @@ auth_ntlm(char *windom, char *keyp, uchar *chal, int len)
static Auth *
auth_ntlmv2(char *windom, char *keyp, uchar *chal, int len)
{
- return auth_proto("mschap2", windom, keyp, chal, len);
+ return auth_proto("ntlmv2", windom, keyp, chal, len);
}
struct {
diff --git a/sys/src/cmd/ip/cifsd/smb.c b/sys/src/cmd/ip/cifsd/smb.c
index af2182097..45a9aff55 100644
--- a/sys/src/cmd/ip/cifsd/smb.c
+++ b/sys/src/cmd/ip/cifsd/smb.c
@@ -46,7 +46,7 @@ err:
if(needauth){
if(smbcs != nil)
auth_freechal(smbcs);
- if(smbcs = auth_challenge("proto=mschap role=server")){
+ if(smbcs = auth_challenge("proto=ntlm role=server")){
c = (uchar*)smbcs->chal;
ce = c + smbcs->nchal;
mode = NEGOTIATE_USER_SECURITY | NEGOTIATE_ENCRYPT_PASSWORDS;
@@ -104,6 +104,7 @@ smbsessionsetupandx(Req *r, uchar *h, uchar *p, uchar *e)
if(smbcs == nil || strlen(user) == 0)
break;
smbcs->user = user;
+ smbcs->dom = dom;
smbcs->nresp = (nte - nt)+sizeof(*mcr)-sizeof(mcr->NTresp);
if(smbcs->nresp < sizeof(*mcr))
smbcs->nresp = sizeof(*mcr);
diff --git a/sys/src/libauth/auth_challenge.c b/sys/src/libauth/auth_challenge.c
index d21841a05..5ab0ee6a1 100644
--- a/sys/src/libauth/auth_challenge.c
+++ b/sys/src/libauth/auth_challenge.c
@@ -74,6 +74,15 @@ auth_response(Chalstate *c)
goto Out;
}
}
+ if(c->dom){
+ if(auth_rpc(c->rpc, "write", c->dom, strlen(c->dom)) != ARok){
+ /*
+ * if this fails we're out of phase with factotum.
+ * give up.
+ */
+ goto Out;
+ }
+ }
if(auth_rpc(c->rpc, "write", c->resp, c->nresp) != ARok){
/*