Index: sys/fs/smbfs/smbfs_smb.c =================================================================== RCS file: /home/ncvs/src/sys/fs/smbfs/smbfs_smb.c,v retrieving revision 1.15 diff -u -r1.15 smbfs_smb.c --- sys/fs/smbfs/smbfs_smb.c 4 May 2005 15:05:46 -0000 1.15 +++ sys/fs/smbfs/smbfs_smb.c 15 Aug 2005 10:43:59 -0000 @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef USE_MD5_HASH #include @@ -509,6 +510,10 @@ if (error) break; mb_put_uint8(mbp, SMB_DT_ASCII); + if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) { + mb_put_padbyte(mbp); + mb_put_uint8(mbp, 0); /* 1st byte of NULL Unicode char */ + } mb_put_uint8(mbp, 0); smb_rq_bend(rqp); error = smb_rq_simple(rqp); @@ -1024,6 +1029,10 @@ mb_put_uint16le(mbp, 0); /* context length */ ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; } else { + if (SMB_UNICODE_STRINGS(vcp)) { + mb_put_padbyte(mbp); + mb_put_uint8(mbp, 0); + } mb_put_uint8(mbp, 0); /* file name length */ mb_put_uint8(mbp, SMB_DT_VARIABLE); mb_put_uint16le(mbp, SMB_SKEYLEN); @@ -1184,7 +1193,7 @@ mb_put_uint32le(mbp, 0); /* resume key */ mb_put_uint16le(mbp, flags); if (ctx->f_rname) - mb_put_mem(mbp, ctx->f_rname, strlen(ctx->f_rname) + 1, MB_MSYSTEM); + mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen + 1, MB_MSYSTEM); else mb_put_uint8(mbp, 0); /* resume file name */ #if 0 @@ -1265,7 +1274,10 @@ smbfs_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp, const char *wildcard, int wclen, int attr, struct smb_cred *scred) { - ctx->f_name = malloc(SMB_MAXFNAMELEN, M_SMBFSDATA, M_WAITOK); + if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { + ctx->f_name = malloc(SMB_MAXFNAMELEN * 2, M_SMBFSDATA, M_WAITOK); + } else + ctx->f_name = malloc(SMB_MAXFNAMELEN, M_SMBFSDATA, M_WAITOK); if (ctx->f_name == NULL) return ENOMEM; ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_NTLM0_12 ? @@ -1344,7 +1356,10 @@ SMBERROR("unexpected info level %d\n", ctx->f_infolevel); return EINVAL; } - nmlen = min(size, SMB_MAXFNAMELEN); + if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { + nmlen = min(size, SMB_MAXFNAMELEN * 2); + } else + nmlen = min(size, SMB_MAXFNAMELEN); cp = ctx->f_name; error = md_get_mem(mbp, cp, nmlen, MB_MSYSTEM); if (error) @@ -1358,8 +1373,12 @@ return EBADRPC; } } - if (nmlen && cp[nmlen - 1] == 0) - nmlen--; + if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { + if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0) + nmlen -= 2; + } else + if (nmlen && cp[nmlen - 1] == 0) + nmlen--; if (nmlen == 0) return EBADRPC; @@ -1443,10 +1462,17 @@ error = smbfs_findnextLM2(ctx, limit); if (error) return error; - if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || - (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && - ctx->f_name[1] == '.')) - continue; + if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { + if ((ctx->f_nmlen == 2 && + *(u_int16_t *)ctx->f_name == htole16(0x002e)) || + (ctx->f_nmlen == 4 && + *(u_int32_t *)ctx->f_name == htole32(0x002e002e))) + continue; + } else + if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || + (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && + ctx->f_name[1] == '.')) + continue; break; } smbfs_fname_tolocal(SSTOVC(ctx->f_ssp), ctx->f_name, &ctx->f_nmlen, Index: sys/fs/smbfs/smbfs_subr.c =================================================================== RCS file: /home/ncvs/src/sys/fs/smbfs/smbfs_subr.c,v retrieving revision 1.8 diff -u -r1.8 smbfs_subr.c --- sys/fs/smbfs/smbfs_subr.c 6 May 2005 20:47:09 -0000 1.8 +++ sys/fs/smbfs/smbfs_subr.c 23 Aug 2005 13:49:46 -0000 @@ -278,7 +278,10 @@ return smb_put_dmem(mbp, vcp, "\\", 2, caseopt);*/ while (i--) { np = *--npp; - error = mb_put_uint8(mbp, '\\'); + if (SMB_UNICODE_STRINGS(vcp)) + error = mb_put_uint16le(mbp, '\\'); + else + error = mb_put_uint8(mbp, '\\'); if (error) break; error = smb_put_dmem(mbp, vcp, np->n_name, np->n_nmlen, caseopt); @@ -296,6 +299,11 @@ int caseopt = SMB_CS_NONE; int error; + if (SMB_UNICODE_STRINGS(vcp)) { + error = mb_put_padbyte(mbp); + if (error) + return error; + } if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) caseopt |= SMB_CS_UPPER; if (dnp != NULL) { @@ -304,7 +312,10 @@ return error; } if (name) { - error = mb_put_uint8(mbp, '\\'); + if (SMB_UNICODE_STRINGS(vcp)) + error = mb_put_uint16le(mbp, '\\'); + else + error = mb_put_uint8(mbp, '\\'); if (error) return error; error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); @@ -312,6 +323,8 @@ return error; } error = mb_put_uint8(mbp, 0); + if (SMB_UNICODE_STRINGS(vcp) && error == 0) + error = mb_put_uint8(mbp, 0); return error; } @@ -339,6 +352,17 @@ error = iconv_conv_case (vcp->vc_tolocal, (const char **)&ibuf, &ilen, &obuf, &olen, copt); + if (error && SMB_UNICODE_STRINGS(vcp)) { + /* + * If using unicode, leaving a file name as it was when + * convert fails will cause a problem because the file name + * will contain NULL. + * Here, put '?' and give converted file name. + */ + *obuf = '?'; + olen--; + error = 0; + } if (!error) { *nmlen = sizeof(outbuf) - olen; memcpy(name, outbuf, *nmlen); Index: sys/kern/subr_mchain.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_mchain.c,v retrieving revision 1.18 diff -u -r1.18 subr_mchain.c --- sys/kern/subr_mchain.c 29 Jul 2005 13:22:36 -0000 1.18 +++ sys/kern/subr_mchain.c 2 Aug 2005 14:57:40 -0000 @@ -129,6 +129,21 @@ } int +mb_put_padbyte(struct mbchain *mbp) +{ + caddr_t dst; + char x = 0; + + dst = mtod(mbp->mb_cur, caddr_t) + mbp->mb_cur->m_len; + + /* only add padding if address is odd */ + if ((unsigned long)dst & 1) + return mb_put_mem(mbp, (caddr_t)&x, 1, MB_MSYSTEM); + else + return 0; +} + +int mb_put_uint8(struct mbchain *mbp, u_int8_t x) { return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); index: sys/modules/libmchain/Makefile =================================================================== RCS file: /home/ncvs/src/sys/modules/libmchain/Makefile,v retrieving revision 1.3 diff -u -r1.3 Makefile --- sys/modules/libmchain/Makefile 14 Dec 2002 00:01:51 -0000 1.3 +++ sys/modules/libmchain/Makefile 2 Aug 2005 14:57:40 -0000 @@ -11,6 +11,7 @@ mb_detach \ mb_fixhdr \ mb_reserve \ + mb_put_padbyte \ mb_put_uint8 \ mb_put_uint16be \ mb_put_uint16le \ Index: sys/netsmb/smb_conn.c =================================================================== RCS file: /home/ncvs/src/sys/netsmb/smb_conn.c,v retrieving revision 1.15 diff -u -r1.15 smb_conn.c --- sys/netsmb/smb_conn.c 13 May 2005 11:27:48 -0000 1.15 +++ sys/netsmb/smb_conn.c 2 Aug 2005 14:57:40 -0000 @@ -448,13 +448,29 @@ goto fail; if (vcspec->servercs[0]) { error = (int)iconv_open(vcspec->servercs, vcspec->localcs, - &vcp->vc_toserver); + &vcp->vc_cp_toserver); if (error) goto fail; error = (int)iconv_open(vcspec->localcs, vcspec->servercs, - &vcp->vc_tolocal); + &vcp->vc_cp_tolocal); if (error) goto fail; + vcp->vc_toserver = vcp->vc_cp_toserver; + vcp->vc_tolocal = vcp->vc_cp_tolocal; + iconv_add(ENCODING_UNICODE, ENCODING_UNICODE, SMB_UNICODE_NAME); + iconv_add(ENCODING_UNICODE, SMB_UNICODE_NAME, ENCODING_UNICODE); + error = (int)iconv_open(SMB_UNICODE_NAME, vcspec->localcs, + &vcp->vc_ucs_toserver); + if (!error) { + error = (int)iconv_open(vcspec->localcs, SMB_UNICODE_NAME, + &vcp->vc_ucs_tolocal); + } + if (error) { + if (vcp->vc_ucs_toserver) + iconv_close(vcp->vc_ucs_toserver); + vcp->vc_ucs_toserver = NULL; + vcp->vc_ucs_tolocal = NULL; + } } error = (int)smb_iod_create(vcp); if (error) @@ -490,9 +506,17 @@ if (vcp->vc_toupper) iconv_close(vcp->vc_toupper); if (vcp->vc_tolocal) - iconv_close(vcp->vc_tolocal); + vcp->vc_tolocal = NULL; if (vcp->vc_toserver) - iconv_close(vcp->vc_toserver); + vcp->vc_toserver = NULL; + if (vcp->vc_cp_tolocal) + iconv_close(vcp->vc_cp_tolocal); + if (vcp->vc_cp_toserver) + iconv_close(vcp->vc_cp_toserver); + if (vcp->vc_ucs_tolocal) + iconv_close(vcp->vc_ucs_tolocal); + if (vcp->vc_ucs_toserver) + iconv_close(vcp->vc_ucs_toserver); smb_co_done(VCTOCP(vcp)); smb_sl_destroy(&vcp->vc_stlock); free(vcp, M_SMBCONN); Index: sys/netsmb/smb_conn.h =================================================================== RCS file: /home/ncvs/src/sys/netsmb/smb_conn.h,v retrieving revision 1.11 diff -u -r1.11 smb_conn.h --- sys/netsmb/smb_conn.h 7 Jan 2005 01:45:49 -0000 1.11 +++ sys/netsmb/smb_conn.h 2 Aug 2005 14:57:40 -0000 @@ -247,6 +247,10 @@ void * vc_toupper; /* local charset */ void * vc_toserver; /* local charset to server one */ void * vc_tolocal; /* server charset to local one */ + void * vc_cp_toserver; /* local charset to server one (using CodePage) */ + void * vc_cp_tolocal; /* server charset to local one (using CodePage) */ + void * vc_ucs_toserver; /* local charset to server one (using UCS-2) */ + void * vc_ucs_tolocal; /* server charset to local one (using UCS-2) */ int vc_number; /* number of this VC from the client side */ int vc_genid; uid_t vc_uid; /* user id of connection */ @@ -278,6 +282,8 @@ #define SMB_UNICODE_STRINGS(vcp) ((vcp)->vc_hflags2 & SMB_FLAGS2_UNICODE) +#define SMB_UNICODE_NAME "UCS-2LE" + /* * smb_share structure describes connection to the given SMB share (tree). * Connection to share is always built on top of the VC. Index: sys/netsmb/smb_smb.c =================================================================== RCS file: /home/ncvs/src/sys/netsmb/smb_smb.c,v retrieving revision 1.13 diff -u -r1.13 smb_smb.c --- sys/netsmb/smb_smb.c 7 Jan 2005 01:45:49 -0000 1.13 +++ sys/netsmb/smb_smb.c 2 Aug 2005 14:57:40 -0000 @@ -127,9 +127,17 @@ u_int8_t wc, stime[8], sblen; u_int16_t dindex, tw, tw1, swlen, bc; int error, maxqsz; + int unicode = SMB_UNICODE_STRINGS(vcp); + void * servercharset = vcp->vc_toserver; + void * localcharset = vcp->vc_tolocal; if (smb_smb_nomux(vcp, scred, __func__) != 0) return EINVAL; + /* Disable Unicode for SMB_COM_NEGOTIATE requests */ + if (unicode) { + vcp->vc_toserver = vcp->vc_cp_toserver; + vcp->vc_tolocal = vcp->vc_cp_tolocal; + } vcp->vc_hflags = 0; vcp->vc_hflags2 = 0; vcp->obj.co_flags &= ~(SMBV_ENCRYPT); @@ -186,7 +194,7 @@ SMBERROR("Unexpected length of security blob (%d)\n", sblen); break; } - error = md_get_uint16(mdp, &bc); + error = md_get_uint16le(mdp, &bc); if (error) break; if (sp->sv_caps & SMB_CAP_EXT_SECURITY) @@ -201,6 +209,13 @@ if (sp->sv_sm & SMB_SM_SIGS_REQUIRE) vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; #endif + if (vcp->vc_ucs_toserver && + sp->sv_caps & SMB_CAP_UNICODE) { + /* + * They do Unicode. + */ + vcp->obj.co_flags |= SMBV_UNICODE; + } vcp->vc_hflags2 |= SMB_FLAGS2_KNOWS_LONG_NAMES; if (dp->d_id == SMB_DIALECT_NTLM0_12 && sp->sv_maxtx < 4096 && @@ -208,7 +223,13 @@ vcp->obj.co_flags |= SMBV_WIN95; SMBSDEBUG("Win95 detected\n"); } - } else if (dp->d_id > SMB_DIALECT_CORE) { + error = 0; + break; + } + vcp->vc_hflags2 &= ~(SMB_FLAGS2_EXT_SEC|SMB_FLAGS2_DFS| + SMB_FLAGS2_ERR_STATUS|SMB_FLAGS2_UNICODE); + unicode = 0; + if (dp->d_id > SMB_DIALECT_CORE) { md_get_uint16le(mdp, &tw); sp->sv_sm = tw; md_get_uint16le(mdp, &tw); @@ -225,7 +246,7 @@ if (swlen > SMB_MAXCHALLENGELEN) break; md_get_uint16(mdp, NULL); /* mbz */ - if (md_get_uint16(mdp, &bc) != 0) + if (md_get_uint16le(mdp, &bc) != 0) break; if (bc < swlen) break; @@ -267,6 +288,12 @@ SMBSDEBUG("MAXTX = %d\n", sp->sv_maxtx); } bad: + /* Restore Unicode conversion state */ + if (unicode) { + vcp->vc_toserver = servercharset; + vcp->vc_tolocal = localcharset; + vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE; + } smb_rq_done(rqp); return error; } @@ -281,9 +308,13 @@ smb_uniptr unipp, ntencpass = NULL; char *pp, *up, *pbuf, *encpass; int error, plen, uniplen, ulen, upper; + u_int32_t caps = 0; upper = 0; + if (vcp->obj.co_flags & SMBV_UNICODE) + caps |= SMB_CAP_UNICODE; + again: vcp->vc_smbuid = SMB_UID_UNKNOWN; @@ -382,8 +413,7 @@ } 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); + mb_put_uint32le(mbp, caps); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_mem(mbp, pp, plen, MB_MSYSTEM); @@ -485,24 +515,13 @@ upper = 0; again: - -#if 0 /* Disable Unicode for SMB_COM_TREE_CONNECT_ANDX requests */ if (SSTOVC(ssp)->vc_hflags2 & SMB_FLAGS2_UNICODE) { vcp = SSTOVC(ssp); - if (vcp->vc_toserver) { - iconv_close(vcp->vc_toserver); - /* Use NULL until UTF-8 -> ASCII works */ - vcp->vc_toserver = NULL; - } - if (vcp->vc_tolocal) { - iconv_close(vcp->vc_tolocal); - /* Use NULL until ASCII -> UTF-8 works*/ - vcp->vc_tolocal = NULL; - } + vcp->vc_toserver = vcp->vc_cp_toserver; + vcp->vc_tolocal = vcp->vc_cp_tolocal; vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE; } -#endif ssp->ss_tid = SMB_TID_UNKNOWN; error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_TREE_CONNECT_ANDX, scred, &rqp); @@ -567,6 +586,15 @@ ssp->ss_tid = rqp->sr_rptid; ssp->ss_vcgenid = vcp->vc_genid; ssp->ss_flags |= SMBS_CONNECTED; + /* + * If the server can speak Unicode then switch + * our converters to do Unicode <--> Local + */ + if (vcp->obj.co_flags & SMBV_UNICODE) { + vcp->vc_toserver = vcp->vc_ucs_toserver; + vcp->vc_tolocal = vcp->vc_ucs_tolocal; + vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE; + } bad: if (encpass) free(encpass, M_SMBTEMP); Index: sys/netsmb/smb_subr.c =================================================================== RCS file: /home/ncvs/src/sys/netsmb/smb_subr.c,v retrieving revision 1.19 diff -u -r1.19 smb_subr.c --- sys/netsmb/smb_subr.c 29 Jul 2005 13:22:36 -0000 1.19 +++ sys/netsmb/smb_subr.c 2 Aug 2005 14:57:40 -0000 @@ -348,6 +348,8 @@ } mbp->mb_copy = smb_copy_iconv; mbp->mb_udata = dp; + if (SMB_UNICODE_STRINGS(vcp)) + mb_put_padbyte(mbp); return mb_put_mem(mbp, src, size, MB_MCUSTOM); } @@ -360,6 +362,8 @@ error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt); if (error) return error; + if (SMB_UNICODE_STRINGS(vcp)) + return mb_put_uint16le(mbp, 0); return mb_put_uint8(mbp, 0); } Index: sys/sys/mchain.h =================================================================== RCS file: /home/ncvs/src/sys/sys/mchain.h,v retrieving revision 1.9 diff -u -r1.9 mchain.h --- sys/sys/mchain.h 29 Jul 2005 13:22:36 -0000 1.9 +++ sys/sys/mchain.h 2 Aug 2005 14:57:40 -0000 @@ -121,6 +121,7 @@ int mb_fixhdr(struct mbchain *mbp); caddr_t mb_reserve(struct mbchain *mbp, int size); +int mb_put_padbyte(struct mbchain *mbp); int mb_put_uint8(struct mbchain *mbp, u_int8_t x); int mb_put_uint16be(struct mbchain *mbp, u_int16_t x); int mb_put_uint16le(struct mbchain *mbp, u_int16_t x);