static int canon(Rune c) { Rune u = toupperrune(c); if (c >= 128 && u < 128) return c; return u; }
ulong namehash(char *s) { ulong h, t; Rune r; h = 0; while(*s){ s += chartorune(&r, s); r = toupperrune(r); t = h & 0xf8000000; h <<= 5; h ^= t>>27; h ^= (ulong)r; } return h; }
static void Sp_toUpperCase(js_State *J) { const char *src = js_tostring(J, 0); char *dst = js_malloc(J, UTFmax * strlen(src) + 1); const char *s = src; char *d = dst; Rune rune; while (*s) { s += chartorune(&rune, s); rune = toupperrune(rune); d += runetochar(d, &rune); } *d = 0; if (js_try(J)) { js_free(J, dst); js_throw(J); } js_pushstring(J, dst); js_endtry(J); js_free(J, dst); }
int CIFSsession(Session *s) { char os[64], *q; Rune r; Pkt *p; enum { mycaps = CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS | CAP_NT_FIND | CAP_STATUS32, }; s->seqrun = 1; /* activate the sequence number generation/checking */ p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX); p8(p, 0xFF); /* No secondary command */ p8(p, 0); /* Reserved (must be zero) */ pl16(p, 0); /* Offset to next command */ pl16(p, MTU); /* my max buffer size */ pl16(p, 1); /* my max multiplexed pending requests */ pl16(p, 0); /* Virtual connection # */ pl32(p, 0); /* Session key (if vc != 0) */ if((s->secmode & SECMODE_PW_ENCRYPT) == 0) { pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size */ pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */ pl32(p, 0); /* Reserved */ pl32(p, mycaps); pbytes(p); for(q = Sess->auth->resp[0]; *q; ){ q += chartorune(&r, q); pl16(p, toupperrune(r)); } pl16(p, 0); for(q = Sess->auth->resp[0]; *q; ){ q += chartorune(&r, q); pl16(p, r); } pl16(p, 0); }else{ pl16(p, Sess->auth->len[0]); /* LM passwd size */ pl16(p, Sess->auth->len[1]); /* NTLM passwd size */ pl32(p, 0); /* Reserved */ pl32(p, mycaps); pbytes(p); pmem(p, Sess->auth->resp[0], Sess->auth->len[0]); pmem(p, Sess->auth->resp[1], Sess->auth->len[1]); } pstr(p, Sess->auth->user); /* Account name */ pstr(p, Sess->auth->windom); /* Primary domain */ pstr(p, "plan9"); /* Client OS */ pstr(p, argv0); /* Client LAN Manager type */ if(cifsrpc(p) == -1){ free(p); return -1; } g8(p); /* Reserved (0) */ gl16(p); /* Offset to next command wordcount */ Sess->isguest = gl16(p) & 1; /* logged in as guest */ gl16(p); gl16(p); /* no security blob here - we don't understand extended security anyway */ gstr(p, os, sizeof os); s->remos = estrdup9p(os); free(p); return 0; }
static Auth * auth_ntlmv2(char *windom, char *keyp, uchar *chal, int len) { int i, n; Rune r; char *p, *u; uchar v1hash[MD5dlen], blip[Bliplen], blob[1024], v2hash[MD5dlen]; uchar c, lm_hmac[MD5dlen], nt_hmac[MD5dlen], nt_sesskey[MD5dlen], lm_sesskey[MD5dlen]; DigestState *ds; UserPasswd *up; static Auth *ap; up = auth_getuserpasswd(auth_getkey, "windom=%s proto=pass service=cifs-ntlmv2 %s", windom, keyp); if(!up) sysfatal("cannot get key - %r"); ap = emalloc9p(sizeof(Auth)); memset(ap, 0, sizeof(ap)); /* Standard says unlimited length, experience says 128 max */ if((n = strlen(up->passwd)) > 128) n = 128; ds = md4(nil, 0, nil, nil); for(i=0, p=up->passwd; i < n; i++) { p += chartorune(&r, p); c = r; md4(&c, 1, nil, ds); c = r >> 8; md4(&c, 1, nil, ds); } md4(nil, 0, v1hash, ds); /* * Some documentation insists that the username must be forced to * uppercase, but the domain name should not be. Other shows both * being forced to uppercase. I am pretty sure this is irrevevant as the * domain name passed from the remote server always seems to be in * uppercase already. */ ds = hmac_t64(nil, 0, v1hash, MD5dlen, nil, nil); u = up->user; while(*u){ u += chartorune(&r, u); r = toupperrune(r); c = r; hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds); c = r >> 8; hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds); } u = windom; while(*u){ u += chartorune(&r, u); c = r; hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds); c = r >> 8; hmac_t64(&c, 1, v1hash, MD5dlen, nil, ds); } hmac_t64(nil, 0, v1hash, MD5dlen, v2hash, ds); ap->user = estrdup9p(up->user); ap->windom = estrdup9p(windom); /* LM v2 */ genrandom(blip, Bliplen); ds = hmac_t64(chal, len, v2hash, MD5dlen, nil, nil); hmac_t64(blip, Bliplen, v2hash, MD5dlen, lm_hmac, ds); ap->len[0] = MD5dlen+Bliplen; ap->resp[0] = emalloc9p(ap->len[0]); memcpy(ap->resp[0], lm_hmac, MD5dlen); memcpy(ap->resp[0]+MD5dlen, blip, Bliplen); /* LM v2 session key */ hmac_t64(lm_hmac, MD5dlen, v2hash, MD5dlen, lm_sesskey, nil); /* LM v2 MAC key */ ap->mackey[0] = emalloc9p(MACkeylen); memcpy(ap->mackey[0], lm_sesskey, MD5dlen); memcpy(ap->mackey[0]+MD5dlen, ap->resp[0], MACkeylen-MD5dlen); /* NTLM v2 */ n = ntv2_blob(blob, sizeof(blob), windom); ds = hmac_t64(chal, len, v2hash, MD5dlen, nil, nil); hmac_t64(blob, n, v2hash, MD5dlen, nt_hmac, ds); ap->len[1] = MD5dlen+n; ap->resp[1] = emalloc9p(ap->len[1]); memcpy(ap->resp[1], nt_hmac, MD5dlen); memcpy(ap->resp[1]+MD5dlen, blob, n); /* * v2hash definitely OK by * the time we get here. */ /* NTLM v2 session key */ hmac_t64(nt_hmac, MD5dlen, v2hash, MD5dlen, nt_sesskey, nil); /* NTLM v2 MAC key */ ap->mackey[1] = emalloc9p(MACkeylen); memcpy(ap->mackey[1], nt_sesskey, MD5dlen); memcpy(ap->mackey[1]+MD5dlen, ap->resp[1], MACkeylen-MD5dlen); free(up); return ap; }
static int ntv2_blob(uchar *blob, int len, char *windom) { int n; uvlong nttime; Rune r; char *d; uchar *p; enum { /* name types */ Beof, /* end of name list */ Bnetbios, /* Netbios machine name */ Bdomain, /* Windows Domain name (NT) */ Bdnsfqdn, /* DNS Fully Qualified Domain Name */ Bdnsname, /* DNS machine name (win2k) */ }; p = blob; *p++ = 1; /* response type */ *p++ = 1; /* max response type understood by client */ *p++ = 0; *p++ = 0; /* 2 bytes reserved */ *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; /* 4 bytes unknown */ nttime = time(nil); /* nt time now */ nttime += 11644473600LL; nttime *= 10000000LL; *p++ = nttime; *p++ = nttime >> 8; *p++ = nttime >> 16; *p++ = nttime >> 24; *p++ = nttime >> 32; *p++ = nttime >> 40; *p++ = nttime >> 48; *p++ = nttime >> 56; genrandom(p, 8); p += 8; /* client nonce */ *p++ = 0x6f; *p++ = 0; *p++ = 0x6e; *p++ = 0; /* unknown data */ *p++ = Bdomain; *p++ = 0; /* name type */ n = utflen(windom) * 2; *p++ = n; *p++ = n >> 8; /* name length */ d = windom; while(*d && p-blob < (len-8)){ d += chartorune(&r, d); r = toupperrune(r); *p++ = r; *p++ = r >> 8; } *p++ = 0; *p++ = Beof; /* name type */ *p++ = 0; *p++ = 0; /* name length */ *p++ = 0x65; *p++ = 0; *p++ = 0; *p++ = 0; /* unknown data */ return p - blob; }