1/* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2013 Apple Inc. 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/malloc.h> 38#include <sys/proc.h> 39#include <sys/lock.h> 40#include <sys/sysctl.h> 41#include <sys/socket.h> 42#include <sys/kpi_mbuf.h> 43#include <sys/vnode.h> 44 45#include <sys/smb_apple.h> 46#include <netsmb/smb.h> 47#include <netsmb/smb_2.h> 48#include <netsmb/smb_conn.h> 49#include <netsmb/smb_rq.h> 50#include <netsmb/smb_subr.h> 51#include <netsmb/smb_dev.h> 52#include <netsmb/smb_converter.h> 53#include <smbclient/ntstatus.h> 54 55 56static const struct { 57 uint32_t nterr; 58 uint32_t errno; 59} nt2errno[] = { 60 {STATUS_LOGON_TYPE_NOT_GRANTED, EAUTH}, 61 {STATUS_NO_LOGON_SERVERS, EAUTH}, /* Server can't talk to domain, just return eauth */ 62 {STATUS_ACCESS_DENIED, EACCES}, 63 {STATUS_ACCESS_VIOLATION, EACCES}, 64 {STATUS_ACCOUNT_DISABLED, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 65 {STATUS_ACCOUNT_RESTRICTION, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 66 {STATUS_LOGIN_TIME_RESTRICTION, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 67 {STATUS_ACCOUNT_LOCKED_OUT, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 68 {STATUS_INVALID_ACCOUNT_NAME, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 69 {STATUS_PWD_TOO_SHORT, SMB_ENETFSPWDPOLICY}, /* violates password policy */ 70 {STATUS_PWD_TOO_RECENT, SMB_ENETFSPWDPOLICY}, /* violates password policy */ 71 {STATUS_PWD_HISTORY_CONFLICT, SMB_ENETFSPWDPOLICY}, /* violates password policy */ 72 {STATUS_ACCOUNT_EXPIRED, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 73 {STATUS_PASSWORD_EXPIRED, SMB_ENETFSPWDNEEDSCHANGE}, /* change your password */ 74 {STATUS_PASSWORD_RESTRICTION, SMB_ENETFSPWDPOLICY}, /* violates password policy */ 75 {STATUS_PASSWORD_MUST_CHANGE, SMB_ENETFSPWDNEEDSCHANGE}, /* change your password */ 76 {STATUS_INVALID_LOGON_HOURS, SMB_ENETFSACCOUNTRESTRICTED}, /* ask the admin for help */ 77 {STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE}, 78 {STATUS_BAD_NETWORK_NAME, ENOENT}, 79 {STATUS_NETWORK_NAME_DELETED, ENOENT}, 80 {STATUS_DUPLICATE_NAME, ENOENT}, 81 {STATUS_BAD_NETWORK_PATH, ENOENT}, 82 {STATUS_BUFFER_TOO_SMALL, E2BIG}, 83 {STATUS_INVALID_BUFFER_SIZE, EIO}, 84 {STATUS_CONFLICTING_ADDRESSES, EADDRINUSE}, 85 {STATUS_CONNECTION_ABORTED, ECONNABORTED}, 86 {STATUS_CONNECTION_DISCONNECTED,ECONNABORTED}, 87 {STATUS_CONNECTION_REFUSED, ECONNREFUSED}, 88 {STATUS_CONNECTION_RESET, ENETRESET}, 89 {STATUS_DEVICE_DOES_NOT_EXIST, ENODEV}, 90 {STATUS_DEVICE_PROTOCOL_ERROR, EPROTO}, 91 {STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY}, 92 {STATUS_DISK_FULL, ENOSPC}, 93 {STATUS_DLL_NOT_FOUND, ENOENT}, 94 {STATUS_END_OF_FILE, ENODATA}, 95 {STATUS_FILE_IS_A_DIRECTORY, EISDIR}, 96 {STATUS_FILE_LOCK_CONFLICT, EIO}, /* Return the IO error (AFP Like) and let the lock code reset it */ 97 {STATUS_LOCK_NOT_GRANTED, EACCES}, 98 {STATUS_FLOAT_INEXACT_RESULT, ERANGE}, 99 {STATUS_FLOAT_OVERFLOW, ERANGE}, 100 {STATUS_FLOAT_UNDERFLOW, ERANGE}, 101 {STATUS_HOST_UNREACHABLE, EHOSTUNREACH}, 102 {STATUS_ILL_FORMED_PASSWORD, EAUTH}, 103 {STATUS_INTEGER_OVERFLOW, ERANGE}, 104 {STATUS_FILE_CLOSED, EBADF}, 105 {STATUS_INVALID_HANDLE, EBADF}, 106 {STATUS_INVALID_PARAMETER, EINVAL}, 107 {STATUS_INVALID_PIPE_STATE, EPIPE}, 108 {STATUS_INVALID_WORKSTATION, EACCES}, 109 {STATUS_IN_PAGE_ERROR, EFAULT}, 110 {STATUS_IO_TIMEOUT, ETIMEDOUT}, 111 {STATUS_IP_ADDRESS_CONFLICT1, EADDRINUSE}, 112 {STATUS_IP_ADDRESS_CONFLICT2, EADDRINUSE}, 113 {STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT}, 114 {STATUS_LOGON_FAILURE, EAUTH}, 115 {STATUS_MEDIA_WRITE_PROTECTED, EROFS}, 116 {STATUS_MEMORY_NOT_ALLOCATED, EFAULT}, 117 {STATUS_NAME_TOO_LONG, ENAMETOOLONG}, 118 {STATUS_NETWORK_ACCESS_DENIED, EACCES}, 119 {STATUS_NETWORK_BUSY, EBUSY}, 120 {STATUS_NETWORK_UNREACHABLE, ENETUNREACH}, 121 {STATUS_NET_WRITE_FAULT, EIO}, 122 {STATUS_NONEXISTENT_SECTOR, ESPIPE}, 123 {STATUS_NOT_A_DIRECTORY, ENOTDIR}, 124 {STATUS_NOT_IMPLEMENTED, ENOTSUP}, 125 {STATUS_NOT_MAPPED_VIEW, EINVAL}, 126 {STATUS_NOT_SUPPORTED, ENOTSUP}, 127 {STATUS_NO_MEDIA, EIO}, 128 {STATUS_IO_DEVICE_ERROR, EIO}, 129 {STATUS_NO_MEDIA_IN_DEVICE, EIO}, 130 {STATUS_NO_MEMORY, ENOMEM}, 131 {STATUS_NO_SUCH_DEVICE, ENODEV}, 132 {STATUS_NO_SUCH_FILE, ENOENT}, 133 {STATUS_OBJECT_NAME_COLLISION, EEXIST}, 134 {STATUS_OBJECT_NAME_NOT_FOUND, ENOENT}, 135 {STATUS_OBJECT_PATH_INVALID, ENOTDIR}, 136 {STATUS_OBJECT_PATH_NOT_FOUND, ENOENT}, 137 {STATUS_PAGEFILE_QUOTA, EDQUOT}, 138 {STATUS_PATH_NOT_COVERED, ENOENT}, 139 {STATUS_NOT_A_REPARSE_POINT, ENOENT}, 140 {STATUS_IO_REPARSE_TAG_MISMATCH,EIO}, 141 {STATUS_IO_REPARSE_DATA_INVALID,EIO}, 142 {STATUS_IO_REPARSE_TAG_NOT_HANDLED, EIO}, 143 {STATUS_REPARSE_POINT_NOT_RESOLVED, ENOENT}, 144 {STATUS_PIPE_BROKEN, EPIPE}, 145 {STATUS_PIPE_BUSY, EPIPE}, 146 {STATUS_PIPE_CONNECTED, EISCONN}, 147 {STATUS_PIPE_DISCONNECTED, EPIPE}, 148 {STATUS_SMB_BAD_TID, ENOENT}, 149 {STATUS_INSUFFICIENT_RESOURCES, EAGAIN}, 150 {STATUS_INSUFF_SERVER_RESOURCES, EAGAIN}, 151 {STATUS_PIPE_NOT_AVAILABLE, ENOSYS}, 152 {STATUS_PORT_CONNECTION_REFUSED,ECONNREFUSED}, 153 {STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE}, 154 {STATUS_PORT_UNREACHABLE, EHOSTUNREACH}, 155 {STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT}, 156 {STATUS_QUOTA_EXCEEDED, EDQUOT}, 157 {STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT}, 158 {STATUS_REMOTE_DISCONNECT, ESHUTDOWN}, 159 {STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED}, 160 {STATUS_REQUEST_NOT_ACCEPTED, EUSERS}, 161 {STATUS_RETRY, EAGAIN}, 162 {STATUS_SHARING_VIOLATION, EBUSY}, 163 {STATUS_TIMER_NOT_CANCELED, ETIME}, 164 {STATUS_TOO_MANY_LINKS, EMLINK}, 165 {STATUS_TOO_MANY_OPENED_FILES, EMFILE}, 166 {STATUS_UNABLE_TO_FREE_VM, EADDRINUSE}, 167 {STATUS_UNSUCCESSFUL, EINVAL}, 168 {STATUS_WRONG_PASSWORD, EAUTH}, 169 {STATUS_DELETE_PENDING, EACCES}, 170 {STATUS_OBJECT_NAME_INVALID, ENAMETOOLONG}, 171 {STATUS_CANNOT_DELETE, EPERM}, 172 {STATUS_RANGE_NOT_LOCKED, EAGAIN}, /* Setting to match F_SETLK, see AFP */ 173 {STATUS_INVALID_LEVEL, ENOTSUP}, 174 {STATUS_MORE_PROCESSING_REQUIRED, EAGAIN}, /* SetupX message requires more processing */ 175 {STATUS_CANCELLED, ECANCELED}, 176 {STATUS_INVALID_INFO_CLASS, EINVAL}, 177 {STATUS_INFO_LENGTH_MISMATCH, EINVAL}, 178 {STATUS_INVALID_DEVICE_REQUEST, EINVAL}, 179 {STATUS_WRONG_VOLUME, ENOENT}, 180 {STATUS_UNRECOGNIZED_MEDIA, EIO}, 181 {STATUS_INVALID_SYSTEM_SERVICE, EINVAL}, 182 {STATUS_INVALID_LOCK_SEQUENCE, EACCES}, 183 {STATUS_ALREADY_COMMITTED, EACCES}, 184 {STATUS_OBJECT_TYPE_MISMATCH, EBADF}, 185 {STATUS_NOT_LOCKED, ENOLCK}, 186 {STATUS_INVALID_PARAMETER_MIX, EINVAL}, 187 {STATUS_PORT_DISCONNECTED, EBADF}, 188 {STATUS_INVALID_PORT_HANDLE, EBADF}, 189 {STATUS_OBJECT_PATH_SYNTAX_BAD, ENOENT}, 190 {STATUS_EAS_NOT_SUPPORTED, ENOTSUP}, 191 {STATUS_EA_TOO_LARGE, ENOATTR}, 192 {STATUS_NONEXISTENT_EA_ENTRY, ENOATTR}, 193 {STATUS_NO_EAS_ON_FILE, ENOATTR}, 194 {STATUS_NO_SUCH_LOGON_SESSION, SMB_ENETFSACCOUNTRESTRICTED}, 195 {STATUS_USER_EXISTS, SMB_ENETFSACCOUNTRESTRICTED}, 196 {STATUS_NO_SUCH_USER, SMB_ENETFSACCOUNTRESTRICTED}, 197 {STATUS_USER_SESSION_DELETED, SMB_ENETFSACCOUNTRESTRICTED}, 198 {STATUS_FILE_INVALID, EIO}, 199 {STATUS_DFS_EXIT_PATH_FOUND, ENOENT}, 200 {STATUS_DEVICE_DATA_ERROR, EIO}, 201 {STATUS_DEVICE_NOT_READY, EAGAIN}, 202 {STATUS_ILLEGAL_FUNCTION, EINVAL}, 203 {STATUS_FILE_RENAMED, ENOENT}, 204 {STATUS_FILE_DELETED, ENOENT}, 205 {STATUS_NO_TRUST_LSA_SECRET, EAUTH}, 206 {STATUS_NO_TRUST_SAM_ACCOUNT, EAUTH}, 207 {STATUS_TRUSTED_DOMAIN_FAILURE, EAUTH}, 208 {STATUS_TRUSTED_RELATIONSHIP_FAILURE, EAUTH}, 209 {0, 0} 210}; 211 212#ifdef SMB_DEBUG 213void smb_hexdump(const char *func, const char *s, unsigned char *buf, size_t inlen) 214{ 215 int32_t addr; 216 int32_t i; 217 int32_t len = (int32_t)inlen; 218 219 printf("%s: hexdump: %s %p length %d inlen %ld\n", func, s, buf, len, inlen); 220 addr = 0; 221 while( addr < len ) 222 { 223 printf("%6.6x - " , addr ); 224 for( i=0; i<16; i++ ) 225 { 226 if( addr+i < len ) 227 printf("%2.2x ", buf[addr+i] ); 228 else 229 printf(" " ); 230 } 231 printf(" \""); 232 for( i=0; i<16; i++ ) 233 { 234 if( addr+i < len ) 235 { 236 if(( buf[addr+i] > 0x19 ) && ( buf[addr+i] < 0x7e ) ) 237 printf("%c", buf[addr+i] ); 238 else 239 printf("."); 240 } 241 } 242 printf("\" \n"); 243 addr += 16; 244 } 245 printf("\" \n"); 246} 247#endif // SMB_DEBUG 248 249char * 250smb_strndup(const char * string, size_t maxlen) 251{ 252 char * result = NULL; 253 size_t size; 254 255 if (!string) { 256 goto finish; 257 } 258 259 size = strnlen(string, maxlen); 260 SMB_MALLOC(result, char *, size + 1, M_SMBSTR, M_WAITOK | M_ZERO); 261 if (!result) { 262 goto finish; 263 } 264 265 memcpy(result, string, size); 266 267finish: 268 return result; 269} 270 271/* Same as the kernel defualt */ 272#define SMB_KALLOC_MAP_SIZE_MAX (128 * 1024 * 1024) 273#define SMB_WAIT_SIZE_MAX (32 * 1024) 274 275/* 276 * duplicate memory block from a user space. 277 */ 278void * smb_memdupin(user_addr_t umem, int len) 279{ 280 int error; 281 char *p; 282 int flags = M_WAITOK; 283 284 /* Never let them allocate something unreasonable */ 285 if ((len < 0) || (len > SMB_KALLOC_MAP_SIZE_MAX)) { 286 SMBERROR("Bad size : %d\n", len); 287 return NULL; 288 } 289 /* Requesting large amount of memory don't wait */ 290 if (len > SMB_WAIT_SIZE_MAX) { 291 flags = M_NOWAIT; 292 } 293 SMB_MALLOC(p, char *, len, M_SMBSTR, flags); 294 if (!p) { 295 SMBDEBUG("malloc failed : %d\n", ENOMEM); 296 return NULL; 297 } 298 error = copyin(umem, p, len); 299 if (error == 0) 300 return p; 301 302 SMBDEBUG("copyin failed : %d\n", error); 303 SMB_FREE(p, M_SMBDATA); 304 return NULL; 305} 306 307/* 308 * duplicate memory block in the kernel space. 309 */ 310void * 311smb_memdup(const void *umem, int len) 312{ 313 char *p; 314 315 if (len > 32 * 1024) 316 return NULL; 317 SMB_MALLOC(p, char *, len, M_SMBSTR, M_WAITOK); 318 if (p == NULL) 319 return NULL; 320 bcopy(umem, p, len); 321 return p; 322} 323 324#ifdef SMB_SOCKETDATA_DEBUG 325void 326m_dumpm(mbuf_t m) { 327 char *p; 328 int len; 329 SMBDEBUG("d="); 330 while(m) { 331 p = mbuf_data(m); 332 len = mbuf_len(m); 333 SMBDEBUG("(%d)",len); 334 while(len--){ 335 SMBDEBUG("%02x ",((int)*(p++)) & 0xff); 336 } 337 m = mbuf_next(m); 338 }; 339 SMBDEBUG("\n"); 340} 341#endif 342 343/* Convert the DOS Class Error to a NTSTATUS error */ 344static uint32_t 345smb_dos_class_err_to_ntstatus(uint16_t dosErr) 346{ 347 switch (dosErr) { 348 case ERRbadfunc: 349 return STATUS_NOT_IMPLEMENTED; 350 case ERRbadfile: 351 return STATUS_NO_SUCH_FILE; 352 case ERRbadpath: 353 return STATUS_OBJECT_PATH_NOT_FOUND; 354 case ERRnofids: 355 return STATUS_TOO_MANY_OPENED_FILES; 356 case ERRnoaccess: 357 return STATUS_ACCESS_DENIED; 358 case ERRbadfid: 359 return STATUS_INVALID_HANDLE; 360 case ERRbadmcb: 361 return STATUS_INSUFF_SERVER_RESOURCES; 362 case ERRnomem: 363 return STATUS_NO_MEMORY; 364 case ERRbadmem: 365 return STATUS_NO_MEMORY; 366 case ERRbadenv: 367 return STATUS_INVALID_PARAMETER; 368 case ERRbadformat: 369 return STATUS_INVALID_PARAMETER; 370 case ERRbadaccess: 371 return STATUS_ACCESS_DENIED; 372 case ERRbaddata: 373 return STATUS_DATA_ERROR; 374 case ERRoutofmem: 375 return STATUS_NO_MEMORY; 376 case ERRbaddrive: 377 return STATUS_INSUFF_SERVER_RESOURCES; 378 case ERRremcd: 379 return STATUS_DIRECTORY_NOT_EMPTY; 380 case ERRdiffdevice: 381 return STATUS_NOT_SAME_DEVICE; 382 case ERRnofiles: 383 return STATUS_NO_MORE_FILES; 384 case ERRwriteprotect: 385 return STATUS_MEDIA_WRITE_PROTECTED; 386 case ERRnotready: 387 return STATUS_DEVICE_NOT_READY; 388 case ERRbadcmd: 389 return STATUS_SMB_BAD_COMMAND; 390 case ERRcrc: 391 return STATUS_DATA_ERROR; 392 case ERRbadlength: 393 return STATUS_INFO_LENGTH_MISMATCH; 394 case ERRsectornotfound: 395 return STATUS_NONEXISTENT_SECTOR; 396 case ERRgeneral: 397 return STATUS_UNSUCCESSFUL; 398 case ERRbadshare: 399 return STATUS_SHARING_VIOLATION; 400 case ERRlock: 401 return STATUS_FILE_LOCK_CONFLICT; 402 case ERRwrongdisk: 403 return STATUS_WRONG_VOLUME; 404 case ERReof: 405 return STATUS_END_OF_FILE; 406 case ERRunsup: 407 return STATUS_NOT_SUPPORTED; 408 case ERRnoipc: 409 return STATUS_BAD_NETWORK_NAME; 410 case ERRnosuchshare: 411 return STATUS_BAD_NETWORK_NAME; 412 case ERRtoomanynames: 413 return STATUS_TOO_MANY_NAMES; 414 case ERRfilexists: 415 return STATUS_OBJECT_NAME_COLLISION; 416 case ERRinvalidparam: 417 return STATUS_INVALID_PARAMETER; 418 case ERRinvalidname: 419 return STATUS_OBJECT_NAME_INVALID; 420 case ERRunknownlevel: 421 return STATUS_INVALID_LEVEL; 422 case ERRdirnotempty: 423 return STATUS_DIRECTORY_NOT_EMPTY; 424 case ERRnotlocked: 425 return STATUS_RANGE_NOT_LOCKED; 426 case ERRrename: 427 return STATUS_OBJECT_NAME_COLLISION; 428 case ERRbadpipe: 429 return STATUS_INVALID_PIPE_STATE; 430 case ERRpipebusy: 431 return STATUS_PIPE_BUSY; 432 case ERRpipeclosing: 433 return STATUS_PIPE_CLOSING; 434 case ERRnotconnected: 435 return STATUS_PIPE_DISCONNECTED; 436 case ERRmoredata: 437 return STATUS_MORE_PROCESSING_REQUIRED; 438 case ERRbadealist: 439 return STATUS_EA_TOO_LARGE; 440 case ERReasunsupported: 441 return STATUS_EAS_NOT_SUPPORTED; 442 case ERRnotifyenumdir: 443 return STATUS_NOTIFY_ENUM_DIR; 444 case ERRinvgroup: 445 return STATUS_NETLOGON_NOT_STARTED; 446 default: 447 break; 448 } 449 return STATUS_UNSUCCESSFUL; 450} 451 452/* Convert the Server Class Error to a NTSTATUS error */ 453static uint32_t 454smb_srv_class_err_to_ntstatus(uint16_t srvErr) 455{ 456 switch (srvErr) { 457 case ERRerror: 458 /* 459 * Non-specific error: resource other than disk space exhausted 460 * (for example, TIDs); or first command was not negotiate; or 461 * multiple negotiates attempted; or internal server error. 462 */ 463 return STATUS_INSUFFICIENT_RESOURCES; 464 case ERRbadpw: 465 return STATUS_WRONG_PASSWORD; 466 case ERRbadpath: 467 return STATUS_PATH_NOT_COVERED; 468 case ERRaccess: 469 return STATUS_NETWORK_ACCESS_DENIED; 470 case ERRinvtid: 471 return STATUS_SMB_BAD_TID; 472 case ERRinvnetname: 473 return STATUS_BAD_NETWORK_NAME; 474 case ERRinvdevice: 475 return STATUS_BAD_DEVICE_TYPE; 476 case ERRinvsess: 477 return STATUS_UNSUCCESSFUL; 478 case ERRworking: 479 return STATUS_UNSUCCESSFUL; 480 case ERRnotme: 481 return STATUS_UNSUCCESSFUL; 482 case ERRbadcmd: 483 return STATUS_SMB_BAD_COMMAND; 484 case ERRqfull: 485 return STATUS_PRINT_QUEUE_FULL; 486 case ERRqtoobig: 487 return STATUS_NO_SPOOL_SPACE; 488 case ERRqeof: 489 return STATUS_UNSUCCESSFUL; 490 case ERRinvpfid: 491 return STATUS_PRINT_CANCELLED; 492 case ERRsmbcmd: 493 return STATUS_NOT_IMPLEMENTED; 494 case ERRsrverror: 495 return STATUS_UNEXPECTED_NETWORK_ERROR; 496 case ERRfilespecs: 497 return STATUS_INVALID_HANDLE; 498 case ERRbadpermits: 499 return STATUS_NETWORK_ACCESS_DENIED; 500 case ERRsetattrmode: 501 return STATUS_INVALID_PARAMETER; 502 case ERRtimeout: 503 return STATUS_IO_TIMEOUT; 504 case ERRnoresource: 505 return STATUS_REQUEST_NOT_ACCEPTED; 506 case ERRtoomanyuids: 507 return STATUS_TOO_MANY_SESSIONS; 508 case ERRbaduid: 509 return STATUS_SMB_BAD_UID; 510 case ERRnotconnected: 511 return STATUS_PIPE_DISCONNECTED; 512 case ERRusempx: 513 return STATUS_NOT_IMPLEMENTED; 514 case ERRusestd: 515 return STATUS_SMB_USE_STANDARD; 516 case ERRcontmpx: 517 return STATUS_NOT_IMPLEMENTED; 518 case ERRaccountExpired: 519 return STATUS_ACCOUNT_EXPIRED; 520 case ERRbadClient: 521 return STATUS_INVALID_WORKSTATION; 522 case ERRbadLogonTime: 523 return STATUS_INVALID_LOGON_HOURS; 524 case ERRpasswordExpired: 525 return STATUS_PASSWORD_EXPIRED; 526 case ERRnosupport: 527 return STATUS_NOT_IMPLEMENTED; 528 default: 529 break; 530 } 531 return STATUS_UNSUCCESSFUL; 532} 533 534/* Convert the Hardware Class Error to a NTSTATUS error */ 535static uint32_t 536smb_hrd_class_err_to_ntstatus(uint16_t hrdErr) 537{ 538 switch (hrdErr) { 539 case ERRnowrite: 540 return STATUS_MEDIA_WRITE_PROTECTED; 541 case ERRbadunit: 542 return STATUS_UNSUCCESSFUL; 543 case ERRnotready: 544 return STATUS_NO_MEDIA_IN_DEVICE; 545 case ERRbadcmd: 546 return STATUS_INVALID_DEVICE_STATE; 547 case ERRdata: 548 return STATUS_DATA_ERROR; 549 case ERRbadreq: 550 return STATUS_DATA_ERROR; 551 case ERRseek: 552 return STATUS_UNSUCCESSFUL; 553 case ERRbadmedia: 554 return STATUS_DISK_CORRUPT_ERROR; 555 case ERRbadsector: 556 return STATUS_NONEXISTENT_SECTOR; 557 case ERRnopaper: 558 return STATUS_DEVICE_PAPER_EMPTY; 559 case ERRwrite: 560 return STATUS_IO_DEVICE_ERROR; 561 case ERRread: 562 return STATUS_IO_DEVICE_ERROR; 563 case ERRgeneral: 564 return STATUS_UNSUCCESSFUL; 565 case ERRbadshare: 566 return STATUS_SHARING_VIOLATION; 567 case ERRlock: 568 return STATUS_FILE_LOCK_CONFLICT; 569 case ERRwrongdisk: 570 return STATUS_WRONG_VOLUME; 571 case ERRFCBunavail: 572 return STATUS_UNSUCCESSFUL; 573 case ERRsharebufexc: 574 return STATUS_UNSUCCESSFUL; 575 case ERRdiskfull: 576 return STATUS_DISK_FULL; 577 default: 578 break; 579 } 580 return STATUS_UNSUCCESSFUL; 581} 582 583uint32_t 584smb_errClassCodes_to_ntstatus(uint8_t errClass, uint16_t errCode) 585{ 586 switch (errClass) { 587 case ERRDOS_Class: 588 return smb_dos_class_err_to_ntstatus(errCode); 589 break; 590 case ERRSRV_Class: 591 return smb_srv_class_err_to_ntstatus(errCode); 592 break; 593 case ERRHRD_Class: 594 return smb_hrd_class_err_to_ntstatus(errCode); 595 break; 596 case SUCCESS_Class: 597 if (!errCode) { 598 return 0; 599 } 600 /* Fall through have no idea what to do here */ 601 default: 602 break; 603 } 604 return STATUS_UNSUCCESSFUL; 605} 606 607static uint32_t 608smb_ntstatus_error_to_errno(uint32_t ntstatus) 609{ 610 int ii; 611 612 for (ii = 0; nt2errno[ii].errno; ii++) 613 if (nt2errno[ii].nterr == ntstatus) 614 return (nt2errno[ii].errno); 615 616 SMBERROR("Couldn't map ntstatus (0x%x) to errno returning EIO\n", ntstatus); 617 return EIO; 618} 619 620static uint32_t 621smb_ntstatus_warning_to_errno(uint32_t ntstatus) 622{ 623 switch (ntstatus) { 624 case STATUS_BUFFER_OVERFLOW: 625 /* Do a special check for STATUS_BUFFER_OVERFLOW; it's not an error. */ 626 return 0; 627 break; 628 case STATUS_NO_MORE_FILES: 629 /* Do a special check for STATUS_NO_MORE_FILES; it's not an error. */ 630 return ENOENT; 631 break; 632 case STATUS_STOPPED_ON_SYMLINK: 633 return EIO; /* May want to change this to access denied, but leave the same error for now */ 634 break; 635 default: 636 break; 637 } 638 /* XXX - How should we treat ntstatus warnings? */ 639 SMBERROR("Couldn't map ntstatus (0x%x) to errno returning EIO\n", ntstatus); 640 return EIO; 641} 642 643uint32_t 644smb_ntstatus_to_errno(uint32_t ntstatus) 645{ 646 switch (ntstatus & STATUS_SEVERITY_MASK) { 647 case STATUS_SEVERITY_SUCCESS: 648 /* 649 * Lion Servers returns STATUS_NOTIFY_ENUM_DIR, which just tells 650 * the notify code that something has changed. Just skip printing 651 * the warning since we know why this is being returned. 652 */ 653 if ((ntstatus == STATUS_SUCCESS) || 654 (ntstatus == STATUS_NOTIFY_ENUM_DIR) || 655 (ntstatus == STATUS_NOTIFY_CLEANUP)) { 656 return 0; 657 } 658 SMBWARNING("STATUS_SEVERITY_SUCCESS ntstatus = 0x%x\n", ntstatus); 659 return 0; 660 break; 661 case STATUS_SEVERITY_INFORMATIONAL: 662 SMBWARNING("STATUS_SEVERITY_INFORMATIONAL ntstatus = 0x%x\n", ntstatus); 663 return 0; 664 break; 665 case STATUS_SEVERITY_WARNING: 666 return smb_ntstatus_warning_to_errno(ntstatus); 667 break; 668 case STATUS_SEVERITY_ERROR: 669 return smb_ntstatus_error_to_errno(ntstatus); 670 break; 671 default: 672 break; 673 } 674 return EIO; 675} 676 677int 678smb_put_dmem(struct mbchain *mbp, const char *src, size_t srcSize, 679 int flags, int usingUnicode, size_t *lenp) 680{ 681 char convbuf[512]; 682 char *utf16Str; 683 char *dst; 684 size_t utf16InLen, utf16OutLen; 685 int error; 686 687 if (srcSize == 0) 688 return 0; 689 /* Just to be safe make sure we have room for the null bytes */ 690 utf16InLen = (srcSize * 2) + 2; 691 /* We need a bigger buffer */ 692 if (utf16InLen > sizeof(convbuf)) { 693 SMB_MALLOC(utf16Str, void *, utf16InLen, M_TEMP, M_WAITOK); 694 if (!utf16Str) 695 return ENOMEM; 696 697 } else { 698 /* Just to be safe behave the same as before */ 699 utf16InLen = sizeof(convbuf); 700 utf16Str = convbuf; 701 } 702 703 utf16OutLen = utf16InLen; 704 dst = utf16Str; 705 706 error = smb_convert_to_network(&src, &srcSize, &dst, &utf16OutLen, flags, 707 usingUnicode); 708 if (error) 709 goto done; 710 711 utf16OutLen = utf16InLen - utf16OutLen; 712 if (usingUnicode) 713 mb_put_padbyte(mbp); 714 error = mb_put_mem(mbp, utf16Str, utf16OutLen, MB_MSYSTEM); 715 if (!error && lenp) 716 *lenp += utf16OutLen; 717done: 718 /* We allocated it so free it */ 719 if (utf16Str != convbuf) { 720 SMB_FREE(utf16Str, M_TEMP); 721 } 722 723 return error; 724} 725 726int smb_put_dstring(struct mbchain *mbp, int usingUnicode, const char *src, 727 size_t maxlen, int flags) 728{ 729 int error; 730 731 error = smb_put_dmem(mbp, src, strnlen(src, maxlen), flags, usingUnicode, NULL); 732 if (error) 733 return error; 734 if (usingUnicode) 735 return mb_put_uint16le(mbp, 0); 736 return mb_put_uint8(mbp, 0); 737} 738