smb_subr.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2000-2001 Boris Popov
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. #include <sys/cdefs.h>
  29. __FBSDID("$FreeBSD$");
  30. #include <sys/param.h>
  31. #include <sys/systm.h>
  32. #include <sys/endian.h>
  33. #include <sys/kernel.h>
  34. #include <sys/malloc.h>
  35. #include <sys/proc.h>
  36. #include <sys/lock.h>
  37. #include <sys/sysctl.h>
  38. #include <sys/socket.h>
  39. #include <sys/signalvar.h>
  40. #include <sys/mbuf.h>
  41. #include <sys/iconv.h>
  42. #include <netsmb/smb.h>
  43. #include <netsmb/smb_conn.h>
  44. #include <netsmb/smb_rq.h>
  45. #include <netsmb/smb_subr.h>
  46. static MALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data");
  47. static MALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data");
  48. MALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data");
  49. smb_unichar smb_unieol = 0;
  50. void
  51. smb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred)
  52. {
  53. if (td) {
  54. scred->scr_td = td;
  55. scred->scr_cred = cred ? cred : td->td_ucred;
  56. } else {
  57. scred->scr_td = NULL;
  58. scred->scr_cred = cred ? cred : NULL;
  59. }
  60. }
  61. int
  62. smb_td_intr(struct thread *td)
  63. {
  64. struct proc *p;
  65. sigset_t tmpset;
  66. if (td == NULL)
  67. return 0;
  68. p = td->td_proc;
  69. PROC_LOCK(p);
  70. tmpset = p->p_siglist;
  71. SIGSETOR(tmpset, td->td_siglist);
  72. SIGSETNAND(tmpset, td->td_sigmask);
  73. mtx_lock(&p->p_sigacts->ps_mtx);
  74. SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
  75. mtx_unlock(&p->p_sigacts->ps_mtx);
  76. if (SIGNOTEMPTY(td->td_siglist) && SMB_SIGMASK(tmpset)) {
  77. PROC_UNLOCK(p);
  78. return EINTR;
  79. }
  80. PROC_UNLOCK(p);
  81. return 0;
  82. }
  83. char *
  84. smb_strdup(const char *s)
  85. {
  86. char *p;
  87. size_t len;
  88. len = s ? strlen(s) + 1 : 1;
  89. p = malloc(len, M_SMBSTR, M_WAITOK);
  90. if (s)
  91. bcopy(s, p, len);
  92. else
  93. *p = 0;
  94. return p;
  95. }
  96. /*
  97. * duplicate string from a user space.
  98. */
  99. char *
  100. smb_strdupin(char *s, size_t maxlen)
  101. {
  102. char *p;
  103. int error;
  104. p = malloc(maxlen + 1, M_SMBSTR, M_WAITOK);
  105. error = copyinstr(s, p, maxlen + 1, NULL);
  106. if (error) {
  107. free(p, M_SMBSTR);
  108. return (NULL);
  109. }
  110. return p;
  111. }
  112. /*
  113. * duplicate memory block from a user space.
  114. */
  115. void *
  116. smb_memdupin(void *umem, size_t len)
  117. {
  118. char *p;
  119. if (len > 8 * 1024)
  120. return NULL;
  121. p = malloc(len, M_SMBSTR, M_WAITOK);
  122. if (copyin(umem, p, len) == 0)
  123. return p;
  124. free(p, M_SMBSTR);
  125. return NULL;
  126. }
  127. /*
  128. * duplicate memory block in the kernel space.
  129. */
  130. void *
  131. smb_memdup(const void *umem, int len)
  132. {
  133. char *p;
  134. if (len > 8 * 1024)
  135. return NULL;
  136. p = malloc(len, M_SMBSTR, M_WAITOK);
  137. if (p == NULL)
  138. return NULL;
  139. bcopy(umem, p, len);
  140. return p;
  141. }
  142. void
  143. smb_strfree(char *s)
  144. {
  145. free(s, M_SMBSTR);
  146. }
  147. void
  148. smb_memfree(void *s)
  149. {
  150. free(s, M_SMBSTR);
  151. }
  152. void *
  153. smb_zmalloc(size_t size, struct malloc_type *type, int flags)
  154. {
  155. return malloc(size, type, flags | M_ZERO);
  156. }
  157. void
  158. smb_strtouni(u_int16_t *dst, const char *src)
  159. {
  160. while (*src) {
  161. *dst++ = htole16(*src++);
  162. }
  163. *dst = 0;
  164. }
  165. #ifdef SMB_SOCKETDATA_DEBUG
  166. void
  167. m_dumpm(struct mbuf *m) {
  168. char *p;
  169. size_t len;
  170. printf("d=");
  171. while(m) {
  172. p=mtod(m,char *);
  173. len=m->m_len;
  174. printf("(%zu)",len);
  175. while(len--){
  176. printf("%02x ",((int)*(p++)) & 0xff);
  177. }
  178. m=m->m_next;
  179. }
  180. printf("\n");
  181. }
  182. #endif
  183. int
  184. smb_maperror(int eclass, int eno)
  185. {
  186. if (eclass == 0 && eno == 0)
  187. return 0;
  188. switch (eclass) {
  189. case ERRDOS:
  190. switch (eno) {
  191. case ERRbadfunc:
  192. case ERRbadmcb:
  193. case ERRbadenv:
  194. case ERRbadformat:
  195. case ERRrmuns:
  196. return EINVAL;
  197. case ERRbadfile:
  198. case ERRbadpath:
  199. case ERRremcd:
  200. case 66: /* nt returns it when share not available */
  201. case 67: /* observed from nt4sp6 when sharename wrong */
  202. return ENOENT;
  203. case ERRnofids:
  204. return EMFILE;
  205. case ERRnoaccess:
  206. case ERRbadshare:
  207. return EACCES;
  208. case ERRbadfid:
  209. return EBADF;
  210. case ERRnomem:
  211. return ENOMEM; /* actually remote no mem... */
  212. case ERRbadmem:
  213. return EFAULT;
  214. case ERRbadaccess:
  215. return EACCES;
  216. case ERRbaddata:
  217. return E2BIG;
  218. case ERRbaddrive:
  219. case ERRnotready: /* nt */
  220. return ENXIO;
  221. case ERRdiffdevice:
  222. return EXDEV;
  223. case ERRnofiles:
  224. return 0; /* eeof ? */
  225. return ETXTBSY;
  226. case ERRlock:
  227. return EDEADLK;
  228. case ERRfilexists:
  229. return EEXIST;
  230. case 123: /* dunno what is it, but samba maps as noent */
  231. return ENOENT;
  232. case 145: /* samba */
  233. return ENOTEMPTY;
  234. case ERRnotlocked:
  235. return 0; /* file become unlocked */
  236. case 183:
  237. return EEXIST;
  238. case ERRquota:
  239. return EDQUOT;
  240. }
  241. break;
  242. case ERRSRV:
  243. switch (eno) {
  244. case ERRerror:
  245. return EINVAL;
  246. case ERRbadpw:
  247. case ERRpasswordExpired:
  248. return EAUTH;
  249. case ERRaccess:
  250. return EACCES;
  251. case ERRinvnid:
  252. return ENETRESET;
  253. case ERRinvnetname:
  254. SMBERROR("NetBIOS name is invalid\n");
  255. return EAUTH;
  256. case 3: /* reserved and returned */
  257. return EIO;
  258. case ERRaccountExpired:
  259. case ERRbadClient:
  260. case ERRbadLogonTime:
  261. return EPERM;
  262. case ERRnosupport:
  263. return EBADRPC;
  264. }
  265. break;
  266. case ERRHRD:
  267. switch (eno) {
  268. case ERRnowrite:
  269. return EROFS;
  270. case ERRbadunit:
  271. return ENODEV;
  272. case ERRnotready:
  273. case ERRbadcmd:
  274. case ERRdata:
  275. return EIO;
  276. case ERRbadreq:
  277. return EBADRPC;
  278. case ERRbadshare:
  279. return ETXTBSY;
  280. case ERRlock:
  281. return EDEADLK;
  282. }
  283. break;
  284. }
  285. SMBERROR("Unmapped error %d:%d\n", eclass, eno);
  286. return EBADRPC;
  287. }
  288. static int
  289. smb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst,
  290. size_t *srclen, size_t *dstlen)
  291. {
  292. int error;
  293. size_t inlen = *srclen, outlen = *dstlen;
  294. error = iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &inlen,
  295. &dst, &outlen);
  296. if (inlen != *srclen || outlen != *dstlen) {
  297. *srclen -= inlen;
  298. *dstlen -= outlen;
  299. return 0;
  300. } else
  301. return error;
  302. }
  303. int
  304. smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
  305. size_t size, int caseopt)
  306. {
  307. struct iconv_drv *dp = vcp->vc_toserver;
  308. if (size == 0)
  309. return 0;
  310. if (dp == NULL) {
  311. return mb_put_mem(mbp, src, size, MB_MSYSTEM);
  312. }
  313. mbp->mb_copy = smb_copy_iconv;
  314. mbp->mb_udata = dp;
  315. if (SMB_UNICODE_STRINGS(vcp))
  316. mb_put_padbyte(mbp);
  317. return mb_put_mem(mbp, src, size, MB_MCUSTOM);
  318. }
  319. int
  320. smb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
  321. int caseopt)
  322. {
  323. int error;
  324. error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt);
  325. if (error)
  326. return error;
  327. if (SMB_UNICODE_STRINGS(vcp))
  328. return mb_put_uint16le(mbp, 0);
  329. return mb_put_uint8(mbp, 0);
  330. }
  331. int
  332. smb_put_asunistring(struct smb_rq *rqp, const char *src)
  333. {
  334. struct mbchain *mbp = &rqp->sr_rq;
  335. struct iconv_drv *dp = rqp->sr_vc->vc_toserver;
  336. u_char c;
  337. int error;
  338. while (*src) {
  339. iconv_convmem(dp, &c, src++, 1);
  340. error = mb_put_uint16le(mbp, c);
  341. if (error)
  342. return error;
  343. }
  344. return mb_put_uint16le(mbp, 0);
  345. }