00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 static const struct {
00034 int err;
00035 const char *message;
00036 } rap_errmap[] = {
00037 {5, "RAP5: User has insufficient privilege" },
00038 {50, "RAP50: Not supported by server" },
00039 {65, "RAP65: Access denied" },
00040 {86, "RAP86: The specified password is invalid" },
00041 {2220, "RAP2220: Group does not exist" },
00042 {2221, "RAP2221: User does not exist" },
00043 {2226, "RAP2226: Operation only permitted on a Primary Domain Controller" },
00044 {2237, "RAP2237: User is not in group" },
00045 {2242, "RAP2242: The password of this user has expired." },
00046 {2243, "RAP2243: The password of this user cannot change." },
00047 {2244, "RAP2244: This password cannot be used now (password history conflict)." },
00048 {2245, "RAP2245: The password is shorter than required." },
00049 {2246, "RAP2246: The password of this user is too recent to change."},
00050
00051
00052 {0x80, "Not listening on called name"},
00053 {0x81, "Not listening for calling name"},
00054 {0x82, "Called name not present"},
00055 {0x83, "Called name present, but insufficient resources"},
00056
00057 {0, NULL}
00058 };
00059
00060
00061
00062
00063
00064 static const char *cli_smb_errstr(struct cli_state *cli)
00065 {
00066 return smb_dos_errstr(cli->inbuf);
00067 }
00068
00069
00070
00071
00072
00073 static NTSTATUS cli_smb_rw_error_to_ntstatus(struct cli_state *cli)
00074 {
00075 switch(cli->smb_rw_error) {
00076 case READ_TIMEOUT:
00077 return NT_STATUS_IO_TIMEOUT;
00078 case READ_EOF:
00079 return NT_STATUS_END_OF_FILE;
00080
00081
00082 case READ_ERROR:
00083 return NT_STATUS_INVALID_NETWORK_RESPONSE;
00084 case WRITE_ERROR:
00085 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
00086 case READ_BAD_SIG:
00087 return NT_STATUS_INVALID_PARAMETER;
00088 default:
00089 break;
00090 }
00091 return NT_STATUS_UNSUCCESSFUL;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 const char *cli_errstr(struct cli_state *cli)
00101 {
00102 static fstring cli_error_message;
00103 uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), errnum;
00104 uint8 errclass;
00105 int i;
00106
00107 if (!cli->initialised) {
00108 fstrcpy(cli_error_message, "[Programmer's error] cli_errstr called on unitialized cli_stat struct!\n");
00109 return cli_error_message;
00110 }
00111
00112
00113 if (cli->fd == -1 && cli->smb_rw_error) {
00114 switch(cli->smb_rw_error) {
00115 case READ_TIMEOUT:
00116 slprintf(cli_error_message, sizeof(cli_error_message) - 1,
00117 "Call timed out: server did not respond after %d milliseconds",
00118 cli->timeout);
00119 break;
00120 case READ_EOF:
00121 slprintf(cli_error_message, sizeof(cli_error_message) - 1,
00122 "Call returned zero bytes (EOF)" );
00123 break;
00124 case READ_ERROR:
00125 slprintf(cli_error_message, sizeof(cli_error_message) - 1,
00126 "Read error: %s", strerror(errno) );
00127 break;
00128 case WRITE_ERROR:
00129 slprintf(cli_error_message, sizeof(cli_error_message) - 1,
00130 "Write error: %s", strerror(errno) );
00131 break;
00132 case READ_BAD_SIG:
00133 slprintf(cli_error_message, sizeof(cli_error_message) - 1,
00134 "Server packet had invalid SMB signature!");
00135 break;
00136 default:
00137 slprintf(cli_error_message, sizeof(cli_error_message) - 1,
00138 "Unknown error code %d\n", cli->smb_rw_error );
00139 break;
00140 }
00141 return cli_error_message;
00142 }
00143
00144
00145 if (cli->rap_error) {
00146 for (i = 0; rap_errmap[i].message != NULL; i++) {
00147 if (rap_errmap[i].err == cli->rap_error) {
00148 return rap_errmap[i].message;
00149 }
00150 }
00151
00152 slprintf(cli_error_message, sizeof(cli_error_message) - 1, "RAP code %d",
00153 cli->rap_error);
00154
00155 return cli_error_message;
00156 }
00157
00158
00159 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
00160 NTSTATUS status = NT_STATUS(IVAL(cli->inbuf,smb_rcls));
00161
00162 return nt_errstr(status);
00163 }
00164
00165 cli_dos_error(cli, &errclass, &errnum);
00166
00167
00168
00169 return cli_smb_errstr(cli);
00170 }
00171
00172
00173
00174
00175
00176
00177 NTSTATUS cli_nt_error(struct cli_state *cli)
00178 {
00179 int flgs2 = SVAL(cli->inbuf,smb_flg2);
00180
00181
00182 if (cli->fd == -1 && cli->smb_rw_error) {
00183 return cli_smb_rw_error_to_ntstatus(cli);
00184 }
00185
00186 if (!(flgs2 & FLAGS2_32_BIT_ERROR_CODES)) {
00187 int e_class = CVAL(cli->inbuf,smb_rcls);
00188 int code = SVAL(cli->inbuf,smb_err);
00189 return dos_to_ntstatus(e_class, code);
00190 }
00191
00192 return NT_STATUS(IVAL(cli->inbuf,smb_rcls));
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode)
00202 {
00203 int flgs2;
00204
00205 if(!cli->initialised) {
00206 return;
00207 }
00208
00209
00210 if (cli->fd == -1 && cli->smb_rw_error) {
00211 NTSTATUS status = cli_smb_rw_error_to_ntstatus(cli);
00212 ntstatus_to_dos( status, eclass, ecode);
00213 return;
00214 }
00215
00216 flgs2 = SVAL(cli->inbuf,smb_flg2);
00217
00218 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
00219 NTSTATUS ntstatus = NT_STATUS(IVAL(cli->inbuf, smb_rcls));
00220 ntstatus_to_dos(ntstatus, eclass, ecode);
00221 return;
00222 }
00223
00224 *eclass = CVAL(cli->inbuf,smb_rcls);
00225 *ecode = SVAL(cli->inbuf,smb_err);
00226 }
00227
00228
00229 static const struct {
00230 NTSTATUS status;
00231 int error;
00232 } nt_errno_map[] = {
00233 {NT_STATUS_ACCESS_VIOLATION, EACCES},
00234 {NT_STATUS_INVALID_HANDLE, EBADF},
00235 {NT_STATUS_ACCESS_DENIED, EACCES},
00236 {NT_STATUS_OBJECT_NAME_NOT_FOUND, ENOENT},
00237 {NT_STATUS_OBJECT_PATH_NOT_FOUND, ENOENT},
00238 {NT_STATUS_SHARING_VIOLATION, EBUSY},
00239 {NT_STATUS_OBJECT_PATH_INVALID, ENOTDIR},
00240 {NT_STATUS_OBJECT_NAME_COLLISION, EEXIST},
00241 {NT_STATUS_PATH_NOT_COVERED, ENOENT},
00242 {NT_STATUS_UNSUCCESSFUL, EINVAL},
00243 {NT_STATUS_NOT_IMPLEMENTED, ENOSYS},
00244 {NT_STATUS_IN_PAGE_ERROR, EFAULT},
00245 {NT_STATUS_BAD_NETWORK_NAME, ENOENT},
00246 #ifdef EDQUOT
00247 {NT_STATUS_PAGEFILE_QUOTA, EDQUOT},
00248 {NT_STATUS_QUOTA_EXCEEDED, EDQUOT},
00249 {NT_STATUS_REGISTRY_QUOTA_LIMIT, EDQUOT},
00250 {NT_STATUS_LICENSE_QUOTA_EXCEEDED, EDQUOT},
00251 #endif
00252 #ifdef ETIME
00253 {NT_STATUS_TIMER_NOT_CANCELED, ETIME},
00254 #endif
00255 {NT_STATUS_INVALID_PARAMETER, EINVAL},
00256 {NT_STATUS_NO_SUCH_DEVICE, ENODEV},
00257 {NT_STATUS_NO_SUCH_FILE, ENOENT},
00258 #ifdef ENODATA
00259 {NT_STATUS_END_OF_FILE, ENODATA},
00260 #endif
00261 #ifdef ENOMEDIUM
00262 {NT_STATUS_NO_MEDIA_IN_DEVICE, ENOMEDIUM},
00263 {NT_STATUS_NO_MEDIA, ENOMEDIUM},
00264 #endif
00265 {NT_STATUS_NONEXISTENT_SECTOR, ESPIPE},
00266 {NT_STATUS_NO_MEMORY, ENOMEM},
00267 {NT_STATUS_CONFLICTING_ADDRESSES, EADDRINUSE},
00268 {NT_STATUS_NOT_MAPPED_VIEW, EINVAL},
00269 {NT_STATUS_UNABLE_TO_FREE_VM, EADDRINUSE},
00270 {NT_STATUS_ACCESS_DENIED, EACCES},
00271 {NT_STATUS_BUFFER_TOO_SMALL, ENOBUFS},
00272 {NT_STATUS_WRONG_PASSWORD, EACCES},
00273 {NT_STATUS_LOGON_FAILURE, EACCES},
00274 {NT_STATUS_INVALID_WORKSTATION, EACCES},
00275 {NT_STATUS_INVALID_LOGON_HOURS, EACCES},
00276 {NT_STATUS_PASSWORD_EXPIRED, EACCES},
00277 {NT_STATUS_ACCOUNT_DISABLED, EACCES},
00278 {NT_STATUS_DISK_FULL, ENOSPC},
00279 {NT_STATUS_INVALID_PIPE_STATE, EPIPE},
00280 {NT_STATUS_PIPE_BUSY, EPIPE},
00281 {NT_STATUS_PIPE_DISCONNECTED, EPIPE},
00282 {NT_STATUS_PIPE_NOT_AVAILABLE, ENOSYS},
00283 {NT_STATUS_FILE_IS_A_DIRECTORY, EISDIR},
00284 {NT_STATUS_NOT_SUPPORTED, ENOSYS},
00285 {NT_STATUS_NOT_A_DIRECTORY, ENOTDIR},
00286 {NT_STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY},
00287 {NT_STATUS_NETWORK_UNREACHABLE, ENETUNREACH},
00288 {NT_STATUS_HOST_UNREACHABLE, EHOSTUNREACH},
00289 {NT_STATUS_CONNECTION_ABORTED, ECONNABORTED},
00290 {NT_STATUS_CONNECTION_REFUSED, ECONNREFUSED},
00291 {NT_STATUS_TOO_MANY_LINKS, EMLINK},
00292 {NT_STATUS_NETWORK_BUSY, EBUSY},
00293 {NT_STATUS_DEVICE_DOES_NOT_EXIST, ENODEV},
00294 #ifdef ELIBACC
00295 {NT_STATUS_DLL_NOT_FOUND, ELIBACC},
00296 #endif
00297 {NT_STATUS_PIPE_BROKEN, EPIPE},
00298 {NT_STATUS_REMOTE_NOT_LISTENING, ECONNREFUSED},
00299 {NT_STATUS_NETWORK_ACCESS_DENIED, EACCES},
00300 {NT_STATUS_TOO_MANY_OPENED_FILES, EMFILE},
00301 #ifdef EPROTO
00302 {NT_STATUS_DEVICE_PROTOCOL_ERROR, EPROTO},
00303 #endif
00304 {NT_STATUS_FLOAT_OVERFLOW, ERANGE},
00305 {NT_STATUS_FLOAT_UNDERFLOW, ERANGE},
00306 {NT_STATUS_INTEGER_OVERFLOW, ERANGE},
00307 {NT_STATUS_MEDIA_WRITE_PROTECTED, EROFS},
00308 {NT_STATUS_PIPE_CONNECTED, EISCONN},
00309 {NT_STATUS_MEMORY_NOT_ALLOCATED, EFAULT},
00310 {NT_STATUS_FLOAT_INEXACT_RESULT, ERANGE},
00311 {NT_STATUS_ILL_FORMED_PASSWORD, EACCES},
00312 {NT_STATUS_PASSWORD_RESTRICTION, EACCES},
00313 {NT_STATUS_ACCOUNT_RESTRICTION, EACCES},
00314 {NT_STATUS_PORT_CONNECTION_REFUSED, ECONNREFUSED},
00315 {NT_STATUS_NAME_TOO_LONG, ENAMETOOLONG},
00316 {NT_STATUS_REMOTE_DISCONNECT, ESHUTDOWN},
00317 {NT_STATUS_CONNECTION_DISCONNECTED, ECONNABORTED},
00318 {NT_STATUS_CONNECTION_RESET, ENETRESET},
00319 #ifdef ENOTUNIQ
00320 {NT_STATUS_IP_ADDRESS_CONFLICT1, ENOTUNIQ},
00321 {NT_STATUS_IP_ADDRESS_CONFLICT2, ENOTUNIQ},
00322 #endif
00323 {NT_STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE},
00324 {NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT},
00325 {NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE},
00326 {NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH},
00327 {NT_STATUS_IO_TIMEOUT, ETIMEDOUT},
00328 {NT_STATUS_RETRY, EAGAIN},
00329 #ifdef ENOTUNIQ
00330 {NT_STATUS_DUPLICATE_NAME, ENOTUNIQ},
00331 #endif
00332 #ifdef ECOMM
00333 {NT_STATUS_NET_WRITE_FAULT, ECOMM},
00334 #endif
00335
00336 {NT_STATUS(0), 0}
00337 };
00338
00339
00340
00341
00342
00343 static int cli_errno_from_nt(NTSTATUS status)
00344 {
00345 int i;
00346 DEBUG(10,("cli_errno_from_nt: 32 bit codes: code=%08x\n", NT_STATUS_V(status)));
00347
00348
00349
00350 if (!(NT_STATUS_V(status) & 0xc0000000)) {
00351 return 0;
00352 }
00353
00354 for (i=0;nt_errno_map[i].error;i++) {
00355 if (NT_STATUS_V(nt_errno_map[i].status) ==
00356 NT_STATUS_V(status)) return nt_errno_map[i].error;
00357 }
00358
00359
00360 return EINVAL;
00361 }
00362
00363
00364
00365
00366 int cli_errno(struct cli_state *cli)
00367 {
00368 NTSTATUS status;
00369
00370 if (cli_is_nt_error(cli)) {
00371 status = cli_nt_error(cli);
00372 return cli_errno_from_nt(status);
00373 }
00374
00375 if (cli_is_dos_error(cli)) {
00376 uint8 eclass;
00377 uint32 ecode;
00378
00379 cli_dos_error(cli, &eclass, &ecode);
00380 status = dos_to_ntstatus(eclass, ecode);
00381 return cli_errno_from_nt(status);
00382 }
00383
00384
00385
00386
00387
00388 status = cli_nt_error(cli);
00389 if (NT_STATUS_V(status) == NT_STATUS_V(STATUS_INACCESSIBLE_SYSTEM_SHORTCUT)) {
00390 return EACCES;
00391 }
00392
00393
00394 return EINVAL;
00395 }
00396
00397
00398
00399 BOOL cli_is_error(struct cli_state *cli)
00400 {
00401 uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), rcls = 0;
00402
00403
00404 if (cli->fd == -1 && cli->smb_rw_error != 0) {
00405 return True;
00406 }
00407
00408 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
00409
00410 rcls = IVAL(cli->inbuf, smb_rcls);
00411 return (rcls & 0xF0000000) == 0xC0000000;
00412 }
00413
00414
00415
00416 rcls = CVAL(cli->inbuf, smb_rcls);
00417 return rcls != 0;
00418 }
00419
00420
00421
00422 BOOL cli_is_nt_error(struct cli_state *cli)
00423 {
00424 uint32 flgs2 = SVAL(cli->inbuf,smb_flg2);
00425
00426
00427 if (cli->fd == -1 && cli->smb_rw_error != 0) {
00428 return True;
00429 }
00430
00431 return cli_is_error(cli) && (flgs2 & FLAGS2_32_BIT_ERROR_CODES);
00432 }
00433
00434
00435
00436 BOOL cli_is_dos_error(struct cli_state *cli)
00437 {
00438 uint32 flgs2 = SVAL(cli->inbuf,smb_flg2);
00439
00440
00441 if (cli->fd == -1 && cli->smb_rw_error != 0) {
00442 return True;
00443 }
00444
00445 return cli_is_error(cli) && !(flgs2 & FLAGS2_32_BIT_ERROR_CODES);
00446 }
00447
00448
00449
00450 NTSTATUS cli_get_nt_error(struct cli_state *cli)
00451 {
00452 if (cli_is_nt_error(cli)) {
00453 return cli_nt_error(cli);
00454 } else if (cli_is_dos_error(cli)) {
00455 uint32 ecode;
00456 uint8 eclass;
00457 cli_dos_error(cli, &eclass, &ecode);
00458 return dos_to_ntstatus(eclass, ecode);
00459 } else {
00460
00461 return NT_STATUS_UNSUCCESSFUL;
00462 }
00463 }
00464
00465
00466
00467
00468 void cli_set_nt_error(struct cli_state *cli, NTSTATUS status)
00469 {
00470 SSVAL(cli->inbuf,smb_flg2, SVAL(cli->inbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
00471 SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status));
00472 }
00473
00474
00475
00476 void cli_reset_error(struct cli_state *cli)
00477 {
00478 if (SVAL(cli->inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES) {
00479 SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(NT_STATUS_OK));
00480 } else {
00481 SCVAL(cli->inbuf,smb_rcls,0);
00482 SSVAL(cli->inbuf,smb_err,0);
00483 }
00484 }