int smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; /* u_int8_t wc; u_int16_t tw, tw1;*/ smb_uniptr unipp, ntencpass = NULL; char *pp, *up, *pbuf, *encpass; int error, plen, uniplen, ulen; vcp->vc_smbuid = SMB_UID_UNKNOWN; if (smb_smb_nomux(vcp, scred, __func__) != 0) return EINVAL; error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX, scred, &rqp); if (error) return error; pbuf = kmalloc(SMB_MAXPASSWORDLEN + 1, M_SMBTEMP, M_WAITOK); encpass = kmalloc(24, M_SMBTEMP, M_WAITOK); if (vcp->vc_sopt.sv_sm & SMB_SM_USER) { iconv_convstr(vcp->vc_toupper, pbuf, smb_vc_getpass(vcp)); iconv_convstr(vcp->vc_toserver, pbuf, pbuf); if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { uniplen = plen = 24; smb_encrypt(pbuf, vcp->vc_ch, encpass); ntencpass = kmalloc(uniplen, M_SMBTEMP, M_WAITOK); iconv_convstr(vcp->vc_toserver, pbuf, smb_vc_getpass(vcp)); smb_ntencrypt(pbuf, vcp->vc_ch, (u_char*)ntencpass); pp = encpass; unipp = ntencpass; } else { plen = strlen(pbuf) + 1; pp = pbuf; uniplen = plen * 2; ntencpass = kmalloc(uniplen, M_SMBTEMP, M_WAITOK); smb_strtouni(ntencpass, smb_vc_getpass(vcp)); plen--; /* * The uniplen is zeroed because Samba cannot deal * with this 2nd cleartext password. This Samba * "bug" is actually a workaround for problems in * Microsoft clients. */ uniplen = 0/*-= 2*/; unipp = ntencpass; } } else { /* * In the share security mode password will be used * only in the tree authentication */ pp = ""; plen = 1; unipp = &smb_unieol; uniplen = 0 /* sizeof(smb_unieol) */; } smb_rq_wstart(rqp); mbp = &rqp->sr_rq; up = vcp->vc_username; ulen = strlen(up) + 1; mb_put_uint8(mbp, 0xff); mb_put_uint8(mbp, 0); mb_put_uint16le(mbp, 0); mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx); mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux); mb_put_uint16le(mbp, vcp->vc_number); mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey); mb_put_uint16le(mbp, plen); if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) { mb_put_uint32le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_mem(mbp, pp, plen, MB_MSYSTEM); smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); } else { mb_put_uint16le(mbp, uniplen); mb_put_uint32le(mbp, 0); /* reserved */ mb_put_uint32le(mbp, vcp->obj.co_flags & SMBV_UNICODE ? SMB_CAP_UNICODE : 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_mem(mbp, pp, plen, MB_MSYSTEM); mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM); smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* AccountName */ smb_put_dstring(mbp, vcp, vcp->vc_domain, SMB_CS_NONE); /* PrimaryDomain */ smb_put_dstring(mbp, vcp, "FreeBSD", SMB_CS_NONE); /* Client's OS */ smb_put_dstring(mbp, vcp, "NETSMB", SMB_CS_NONE); /* Client name */ } smb_rq_bend(rqp); if (ntencpass) kfree(ntencpass, M_SMBTEMP); error = smb_rq_simple(rqp); SMBSDEBUG("%d\n", error); if (error) { if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnoaccess) error = EAUTH; goto bad; } vcp->vc_smbuid = rqp->sr_rpuid; bad: kfree(encpass, M_SMBTEMP); kfree(pbuf, M_SMBTEMP); smb_rq_done(rqp); return error; }
int smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; const smb_unichar *unipp; smb_uniptr ntencpass = NULL; char *up, *pbuf, *encpass; const char *pp; int error, plen, uniplen, ulen, upper; KASSERT(scred->scr_l == vcp->vc_iod->iod_l); upper = 0; again: vcp->vc_smbuid = SMB_UID_UNKNOWN; error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX, scred, &rqp); if (error) return error; pbuf = malloc(SMB_MAXPASSWORDLEN + 1, M_SMBTEMP, M_WAITOK); encpass = malloc(24, M_SMBTEMP, M_WAITOK); if (vcp->vc_sopt.sv_sm & SMB_SM_USER) { /* * We try w/o uppercasing first so Samba mixed case * passwords work. If that fails we come back and try * uppercasing to satisfy OS/2 and Windows for Workgroups. */ if (upper) { iconv_convstr(vcp->vc_toupper, pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN + 1); } else { strlcpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN + 1); } if (!SMB_UNICODE_STRINGS(vcp)) iconv_convstr(vcp->vc_toserver, pbuf, pbuf, SMB_MAXPASSWORDLEN + 1); if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { uniplen = plen = 24; smb_encrypt(pbuf, vcp->vc_ch, encpass); ntencpass = malloc(uniplen, M_SMBTEMP, M_WAITOK); if (SMB_UNICODE_STRINGS(vcp)) { strlcpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN + 1); } else iconv_convstr(vcp->vc_toserver, pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN + 1); smb_ntencrypt(pbuf, vcp->vc_ch, (u_char*)ntencpass); pp = encpass; unipp = ntencpass; } else { plen = strlen(pbuf) + 1; pp = pbuf; uniplen = plen * 2; ntencpass = malloc(uniplen, M_SMBTEMP, M_WAITOK); smb_strtouni(ntencpass, smb_vc_getpass(vcp)); plen--; /* * The uniplen is zeroed because Samba cannot deal * with this 2nd cleartext password. This Samba * "bug" is actually a workaround for problems in * Microsoft clients. */ uniplen = 0/*-= 2*/; unipp = ntencpass; } } else { /* * In the share security mode password will be used * only in the tree authentication */ pp = ""; plen = 1; unipp = &smb_unieol; uniplen = 0; } smb_rq_wstart(rqp); mbp = &rqp->sr_rq; up = vcp->vc_username; ulen = strlen(up) + 1; /* * If userid is null we are attempting anonymous browse login * so passwords must be zero length. */ if (ulen == 1) plen = uniplen = 0; mb_put_uint8(mbp, 0xff); mb_put_uint8(mbp, 0); mb_put_uint16le(mbp, 0); mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx); mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux); mb_put_uint16le(mbp, vcp->vc_number); mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey); mb_put_uint16le(mbp, plen); if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) { mb_put_uint32le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_mem(mbp, pp, plen, MB_MSYSTEM); smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); } else { mb_put_uint16le(mbp, uniplen); mb_put_uint32le(mbp, 0); /* reserved */ mb_put_uint32le(mbp, vcp->obj.co_flags & SMBV_UNICODE ? SMB_CAP_UNICODE : 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_mem(mbp, pp, plen, MB_MSYSTEM); mb_put_mem(mbp, (const void *)unipp, uniplen, MB_MSYSTEM); smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* AccountName */ smb_put_dstring(mbp, vcp, vcp->vc_domain, SMB_CS_NONE); /* PrimaryDomain */ smb_put_dstring(mbp, vcp, "NetBSD", SMB_CS_NONE); /* Client's OS */ smb_put_dstring(mbp, vcp, "NETSMB", SMB_CS_NONE); /* Client name */ } smb_rq_bend(rqp); if (ntencpass) free(ntencpass, M_SMBTEMP); error = smb_rq_simple(rqp); SMBSDEBUG(("%d\n", error)); if (error) { if (error == EACCES) error = EAUTH; goto bad; } vcp->vc_smbuid = rqp->sr_rpuid; bad: free(encpass, M_SMBTEMP); free(pbuf, M_SMBTEMP); smb_rq_done(rqp); if (error && !upper && vcp->vc_sopt.sv_sm & SMB_SM_USER) { upper = 1; goto again; } return error; }