1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * - Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * - Neither the name of The Storage Networking Industry Association (SNIA) 23 * nor the names of its contributors may be used to endorse or promote 24 * products derived from this software without specific prior written 25 * permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 /* Copyright (c) 2007, The Storage Networking Industry Association. */ 40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 41 /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ 42 43 #include <sys/types.h> 44 #include <errno.h> 45 #include <pwd.h> 46 #include <sys/socket.h> 47 #include <netinet/in.h> 48 #include <sys/queue.h> 49 #include <arpa/inet.h> 50 #include <md5.h> 51 #include <shadow.h> 52 #include <crypt.h> 53 #include <alloca.h> 54 #include "ndmpd_common.h" 55 #include "ndmpd.h" 56 #include <libndmp.h> 57 #include <ndmpd_door.h> 58 #include <security/pam_appl.h> 59 60 61 static int ndmpd_connect_auth_text(char *uname, char *auth_id, 62 char *auth_password); 63 static int ndmpd_connect_auth_md5(char *uname, char *auth_id, char *auth_digest, 64 unsigned char *auth_challenge); 65 static struct conn_list *ndmp_connect_list_find(ndmp_connection_t *connection); 66 static void create_md5_digest(unsigned char *digest, char *passwd, 67 unsigned char *challenge); 68 static struct conn_list *ndmp_connect_list_find_id(int id); 69 70 /* routines for connection info */ 71 void ndmp_connect_list_get(ndmp_door_ctx_t *enc_ctx); 72 static void connection_get(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx); 73 static void ndmp_connect_get_conn(struct conn_list *clp, 74 ndmp_door_ctx_t *enc_ctx); 75 static void ndmp_connect_get_v2(ndmp_connection_t *connection, 76 ndmp_door_ctx_t *enc_ctx); 77 static void ndmp_connect_get_scsi_v2(ndmpd_session_t *session, 78 ndmp_door_ctx_t *enc_ctx); 79 static void ndmp_connect_get_tape_v2(ndmpd_session_t *session, 80 ndmp_door_ctx_t *enc_ctx); 81 static void ndmp_connect_get_mover_v2(ndmpd_session_t *session, 82 ndmp_door_ctx_t *enc_ctx); 83 static void ndmp_connect_get_data_v2(ndmpd_session_t *session, 84 ndmp_door_ctx_t *enc_ctx); 85 static void ndmp_connect_get_v3(ndmp_connection_t *connection, 86 ndmp_door_ctx_t *enc_ctx); 87 static void ndmp_connect_get_mover_v3(ndmpd_session_t *session, 88 ndmp_door_ctx_t *enc_ctx); 89 static void ndmp_connect_get_data_v3(ndmpd_session_t *session, 90 ndmp_door_ctx_t *enc_ctx); 91 void ndmpd_get_devs(ndmp_door_ctx_t *enc_ctx); 92 93 #ifndef LIST_FOREACH 94 #define LIST_FOREACH(var, head, field) \ 95 for ((var) = (head)->lh_first; (var); (var) = (var)->field.le_next) 96 #endif /* LIST_FOREACH */ 97 98 /* 99 * List of active connections. 100 */ 101 struct conn_list { 102 LIST_ENTRY(conn_list) cl_q; 103 int cl_id; 104 ndmp_connection_t *cl_conn; 105 }; 106 LIST_HEAD(cl_head, conn_list); 107 108 /* 109 * Head of the active connections. 110 */ 111 static struct cl_head cl_head; 112 113 mutex_t cl_mutex = DEFAULTMUTEX; 114 115 116 /* 117 * Set this variable to non-zero to print verbose information. 118 */ 119 int ndmp_connect_print_verbose = 0; 120 121 122 /* 123 * ************************************************************************ 124 * NDMP V2 HANDLERS 125 * ************************************************************************ 126 */ 127 128 /* 129 * ndmpd_connect_open_v2 130 * 131 * This handler sets the protocol version to be used on the connection. 132 * 133 * Parameters: 134 * connection (input) - connection handle. 135 * body (input) - request message body. 136 * 137 * Returns: 138 * void 139 */ 140 141 void 142 ndmpd_connect_open_v2(ndmp_connection_t *connection, void *body) 143 { 144 ndmp_connect_open_request *request = (ndmp_connect_open_request *)body; 145 ndmp_connect_open_reply reply; 146 ndmpd_session_t *session; 147 148 reply.error = NDMP_NO_ERR; 149 150 if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection))) 151 return; 152 153 if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE || 154 session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) 155 reply.error = NDMP_ILLEGAL_STATE_ERR; 156 else if (request->protocol_version > ndmp_ver) 157 reply.error = NDMP_ILLEGAL_ARGS_ERR; 158 159 ndmp_send_reply(connection, (void *) &reply, 160 "sending connect_open reply"); 161 162 /* 163 * Set the protocol version. 164 * Must wait until after sending the reply since the reply 165 * must be sent using the same protocol version that was used 166 * to process the request. 167 */ 168 if (reply.error == NDMP_NO_ERR) { 169 NDMP_LOG(LOG_DEBUG, "set ver to: %d", 170 request->protocol_version); 171 ndmp_set_version(connection, request->protocol_version); 172 session->ns_protocol_version = request->protocol_version; 173 } 174 } 175 176 177 /* 178 * ndmpd_connect_client_auth_v2 179 * 180 * This handler authorizes the NDMP connection. 181 * 182 * Parameters: 183 * connection (input) - connection handle. 184 * msginfo (input) - request message. 185 * 186 * Returns: 187 * void 188 */ 189 void 190 ndmpd_connect_client_auth_v2(ndmp_connection_t *connection, void *body) 191 { 192 ndmp_connect_client_auth_request *request; 193 ndmp_connect_client_auth_reply reply; 194 ndmp_auth_text *auth; 195 ndmpd_session_t *session; 196 ndmp_auth_md5 *md5; 197 unsigned char md5_digest[16]; 198 char *passwd, *dec_passwd; 199 char *uname; 200 201 request = (ndmp_connect_client_auth_request *)body; 202 NDMP_LOG(LOG_DEBUG, "auth_type:%s", 203 request->auth_data.auth_type == NDMP_AUTH_NONE ? "None" : 204 (request->auth_data.auth_type == NDMP_AUTH_TEXT ? "Text" : 205 (request->auth_data.auth_type == NDMP_AUTH_MD5 ? "MD5" : 206 "Invalid"))); 207 208 reply.error = NDMP_NO_ERR; 209 210 switch (request->auth_data.auth_type) { 211 case NDMP_AUTH_NONE: 212 /* 213 * Allow no authorization for development. 214 * Comment the following for a non-secure production server. 215 */ 216 NDMP_LOG(LOG_ERR, "Authorization denied."); 217 NDMP_LOG(LOG_ERR, 218 "Authorization type should be md5 or cleartext."); 219 reply.error = NDMP_ILLEGAL_ARGS_ERR; 220 ndmpd_audit_connect(connection, EINVAL); 221 break; 222 223 case NDMP_AUTH_TEXT: 224 /* Check authorization. */ 225 if ((uname = ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME)) == NULL || 226 *uname == 0) { 227 NDMP_LOG(LOG_ERR, "Authorization denied."); 228 NDMP_LOG(LOG_ERR, "User name is not set at server."); 229 reply.error = NDMP_NOT_AUTHORIZED_ERR; 230 ndmp_set_authorized(connection, FALSE); 231 ndmp_send_reply(connection, (void *) &reply, 232 "sending ndmp_connect_client_auth reply"); 233 ndmpd_audit_connect(connection, 234 ADT_FAIL_PAM + PAM_AUTH_ERR); 235 return; 236 } 237 auth = &request->auth_data.ndmp_auth_data_u.auth_text; 238 if (strcmp(uname, auth->user) != 0) { 239 NDMP_LOG(LOG_ERR, 240 "Authorization denied. Not a valid user."); 241 reply.error = NDMP_NOT_AUTHORIZED_ERR; 242 ndmpd_audit_connect(connection, 243 ADT_FAIL_PAM + PAM_AUTH_ERR); 244 break; 245 } 246 passwd = ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD); 247 if (!passwd || !*passwd) { 248 NDMP_LOG(LOG_ERR, "Authorization denied."); 249 NDMP_LOG(LOG_ERR, 250 "Cleartext password is not set at server."); 251 reply.error = NDMP_NOT_AUTHORIZED_ERR; 252 ndmp_set_authorized(connection, FALSE); 253 ndmp_send_reply(connection, (void *) &reply, 254 "sending ndmp_connect_client_auth reply"); 255 ndmpd_audit_connect(connection, 256 ADT_FAIL_PAM + PAM_AUTH_ERR); 257 return; 258 } else { 259 dec_passwd = ndmp_base64_decode(passwd); 260 } 261 if (!dec_passwd || !*dec_passwd || 262 strcmp(auth->password, dec_passwd) != 0) { 263 NDMP_LOG(LOG_ERR, 264 "Authorization denied. Invalid password."); 265 reply.error = NDMP_NOT_AUTHORIZED_ERR; 266 } else { 267 NDMP_LOG(LOG_DEBUG, "Authorization granted."); 268 } 269 ndmpd_audit_connect(connection, reply.error ? 270 ADT_FAIL_PAM + PAM_AUTH_ERR : 0); 271 272 free(dec_passwd); 273 break; 274 275 case NDMP_AUTH_MD5: 276 /* Check authorization. */ 277 if ((uname = ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME)) == NULL || 278 *uname == 0) { 279 NDMP_LOG(LOG_ERR, "Authorization denied."); 280 NDMP_LOG(LOG_ERR, "User name is not set at server."); 281 reply.error = NDMP_NOT_AUTHORIZED_ERR; 282 ndmp_set_authorized(connection, FALSE); 283 ndmp_send_reply(connection, (void *) &reply, 284 "sending ndmp_connect_client_auth reply"); 285 ndmpd_audit_connect(connection, 286 ADT_FAIL_PAM + PAM_AUTH_ERR); 287 return; 288 } 289 md5 = &request->auth_data.ndmp_auth_data_u.auth_md5; 290 passwd = ndmpd_get_prop(NDMP_CRAM_MD5_PASSWORD); 291 if (!passwd || !*passwd) { 292 NDMP_LOG(LOG_ERR, "Authorization denied."); 293 NDMP_LOG(LOG_ERR, "MD5 password is not set at server."); 294 reply.error = NDMP_NOT_AUTHORIZED_ERR; 295 ndmp_set_authorized(connection, FALSE); 296 ndmp_send_reply(connection, (void *) &reply, 297 "sending ndmp_connect_client_auth reply"); 298 ndmpd_audit_connect(connection, 299 ADT_FAIL_PAM + PAM_AUTH_ERR); 300 return; 301 } else { 302 dec_passwd = ndmp_base64_decode(passwd); 303 } 304 session = ndmp_get_client_data(connection); 305 create_md5_digest(md5_digest, dec_passwd, 306 session->ns_challenge); 307 308 if (strcmp(uname, md5->user) != 0) { 309 NDMP_LOG(LOG_ERR, 310 "Authorization denied. Not a valid user."); 311 reply.error = NDMP_NOT_AUTHORIZED_ERR; 312 } else if (memcmp(md5_digest, md5->auth_digest, 313 sizeof (md5_digest)) != 0) { 314 NDMP_LOG(LOG_ERR, 315 "Authorization denied. Invalid password."); 316 reply.error = NDMP_NOT_AUTHORIZED_ERR; 317 } else { 318 NDMP_LOG(LOG_DEBUG, "Authorization granted"); 319 } 320 ndmpd_audit_connect(connection, reply.error ? 321 ADT_FAIL_PAM + PAM_AUTH_ERR : 0); 322 323 free(dec_passwd); 324 break; 325 326 default: 327 reply.error = NDMP_ILLEGAL_ARGS_ERR; 328 } 329 330 if (reply.error == NDMP_NO_ERR) 331 ndmp_set_authorized(connection, TRUE); 332 else 333 ndmp_set_authorized(connection, FALSE); 334 335 ndmp_send_reply(connection, (void *) &reply, 336 "sending ndmp_connect_client_auth reply"); 337 } 338 339 340 /* 341 * ndmpd_connect_server_auth_v2 342 * 343 * This handler authenticates the server to the client. 344 * 345 * Parameters: 346 * connection (input) - connection handle. 347 * msginfo (input) - request message. 348 * 349 * Returns: 350 * void 351 */ 352 void 353 ndmpd_connect_server_auth_v2(ndmp_connection_t *connection, void *body) 354 { 355 ndmp_connect_server_auth_request *request; 356 ndmp_connect_server_auth_reply reply; 357 358 request = (ndmp_connect_server_auth_request *)body; 359 360 NDMP_LOG(LOG_DEBUG, "auth_type:%s", 361 request->client_attr.auth_type == NDMP_AUTH_NONE ? "None" : 362 (request->client_attr.auth_type == NDMP_AUTH_TEXT ? "Text" : 363 (request->client_attr.auth_type == NDMP_AUTH_MD5 ? "MD5" : 364 "Invalid"))); 365 366 reply.error = NDMP_NO_ERR; 367 reply.auth_result.auth_type = request->client_attr.auth_type; 368 switch (request->client_attr.auth_type) { 369 case NDMP_AUTH_NONE: 370 break; 371 372 case NDMP_AUTH_TEXT: 373 reply.auth_result.ndmp_auth_data_u.auth_text.user = "ndmpd"; 374 reply.auth_result.ndmp_auth_data_u.auth_text.password = 375 "ndmpsdk"; 376 break; 377 378 case NDMP_AUTH_MD5: 379 reply.error = NDMP_ILLEGAL_ARGS_ERR; 380 break; 381 382 default: 383 reply.error = NDMP_ILLEGAL_ARGS_ERR; 384 } 385 386 ndmp_send_reply(connection, (void *) &reply, 387 "sending ndmp_connect_auth reply"); 388 } 389 390 391 /* 392 * ndmpd_connect_close_v2 393 * 394 * This handler closes the connection. 395 * 396 * Parameters: 397 * connection (input) - connection handle. 398 * msginfo (input) - request message. 399 * 400 * Returns: 401 * void 402 */ 403 /*ARGSUSED*/ 404 void 405 ndmpd_connect_close_v2(ndmp_connection_t *connection, void *body) 406 { 407 ndmpd_session_t *session; 408 409 if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) { 410 (void) ndmp_close(connection); 411 session->ns_eof = TRUE; 412 } 413 } 414 415 /* 416 * ************************************************************************ 417 * NDMP V3 HANDLERS 418 * ************************************************************************ 419 */ 420 421 /* 422 * ndmpd_connect_client_auth_v3 423 * 424 * This handler authorizes the NDMP connection. 425 * 426 * Parameters: 427 * connection (input) - connection handle. 428 * msginfo (input) - request message. 429 * 430 * Returns: 431 * void 432 */ 433 void 434 ndmpd_connect_client_auth_v3(ndmp_connection_t *connection, void *body) 435 { 436 ndmp_connect_client_auth_request_v3 *request; 437 ndmp_connect_client_auth_reply_v3 reply; 438 ndmp_auth_text_v3 *auth; 439 ndmpd_session_t *session; 440 ndmp_auth_md5_v3 *md5; 441 struct in_addr addr; 442 char *uname; 443 char *type; 444 445 request = (ndmp_connect_client_auth_request_v3 *)body; 446 NDMP_LOG(LOG_DEBUG, "auth_type %s", 447 request->auth_data.auth_type == NDMP_AUTH_NONE ? "None" : 448 request->auth_data.auth_type == NDMP_AUTH_TEXT ? "Text" : 449 request->auth_data.auth_type == NDMP_AUTH_MD5 ? "MD5" : "Invalid"); 450 451 reply.error = NDMP_NO_ERR; 452 453 switch (request->auth_data.auth_type) { 454 case NDMP_AUTH_NONE: 455 type = "none"; 456 reply.error = NDMP_NOT_SUPPORTED_ERR; 457 ndmpd_audit_connect(connection, ENOTSUP); 458 break; 459 460 case NDMP_AUTH_TEXT: 461 /* Check authorization. */ 462 if ((uname = ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME)) == NULL || 463 *uname == 0) { 464 NDMP_LOG(LOG_ERR, "Authorization denied."); 465 NDMP_LOG(LOG_ERR, "User name is not set at server."); 466 reply.error = NDMP_NOT_AUTHORIZED_ERR; 467 ndmp_set_authorized(connection, FALSE); 468 ndmp_send_reply(connection, (void *) &reply, 469 "sending ndmp_connect_client_auth reply"); 470 ndmpd_audit_connect(connection, 471 ADT_FAIL_PAM + PAM_AUTH_ERR); 472 return; 473 } 474 type = "text"; 475 auth = &request->auth_data.ndmp_auth_data_v3_u.auth_text; 476 reply.error = ndmpd_connect_auth_text(uname, auth->auth_id, 477 auth->auth_password); 478 ndmpd_audit_connect(connection, reply.error ? 479 ADT_FAIL_PAM + PAM_AUTH_ERR : 0); 480 break; 481 482 case NDMP_AUTH_MD5: 483 /* Check authorization. */ 484 if ((uname = ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME)) == NULL || 485 *uname == 0) { 486 NDMP_LOG(LOG_ERR, "Authorization denied."); 487 NDMP_LOG(LOG_ERR, "User name is not set at server."); 488 reply.error = NDMP_NOT_AUTHORIZED_ERR; 489 ndmp_set_authorized(connection, FALSE); 490 ndmp_send_reply(connection, (void *) &reply, 491 "sending ndmp_connect_client_auth reply"); 492 ndmpd_audit_connect(connection, 493 ADT_FAIL_PAM + PAM_AUTH_ERR); 494 return; 495 } 496 type = "md5"; 497 session = ndmp_get_client_data(connection); 498 md5 = &request->auth_data.ndmp_auth_data_v3_u.auth_md5; 499 reply.error = ndmpd_connect_auth_md5(uname, md5->auth_id, 500 md5->auth_digest, session->ns_challenge); 501 ndmpd_audit_connect(connection, reply.error ? 502 ADT_FAIL_PAM + PAM_AUTH_ERR : 0); 503 break; 504 505 default: 506 type = "unknown"; 507 reply.error = NDMP_ILLEGAL_ARGS_ERR; 508 ndmpd_audit_connect(connection, EINVAL); 509 } 510 511 if (reply.error == NDMP_NO_ERR) { 512 ndmp_set_authorized(connection, TRUE); 513 } else { 514 ndmp_set_authorized(connection, FALSE); 515 if (tcp_get_peer(connection->conn_sock, &addr.s_addr, 516 NULL) != -1) { 517 NDMP_LOG(LOG_ERR, 518 "Authorization(%s) denied for %s.", type, 519 inet_ntoa(IN_ADDR(addr))); 520 } 521 } 522 523 ndmp_send_reply(connection, (void *) &reply, 524 "sending ndmp_connect_auth reply"); 525 } 526 527 528 /* 529 * ndmpd_connect_close_v3 530 * 531 * Close the connection to the DMA. 532 * Send the SHUTDOWN message before closing the socket connection to the DMA. 533 * 534 * Parameters: 535 * connection (input) - connection handle. 536 * msginfo (input) - request message. 537 * 538 * Returns: 539 * void 540 */ 541 /*ARGSUSED*/ 542 void 543 ndmpd_connect_close_v3(ndmp_connection_t *connection, void *body) 544 { 545 ndmpd_session_t *session; 546 ndmp_lbr_params_t *nlp; 547 ndmp_notify_connected_request req; 548 549 if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection))) 550 return; 551 if ((nlp = ndmp_get_nlp(session)) == NULL) 552 return; 553 554 NDMP_LOG(LOG_DEBUG, "ver: %u", 555 session->ns_protocol_version); 556 557 /* Send the SHUTDOWN message before closing the connection. */ 558 req.reason = NDMP_SHUTDOWN; 559 req.protocol_version = session->ns_protocol_version; 560 req.text_reason = "Connection closed by server."; 561 562 if (ndmp_send_request(connection, NDMP_NOTIFY_CONNECTION_STATUS, 563 NDMP_NO_ERR, (void *) &req, 0) < 0) { 564 NDMP_LOG(LOG_NOTICE, "Sending connection shutdown notify"); 565 return; 566 } 567 568 (void) mutex_lock(&nlp->nlp_mtx); 569 ndmp_close(connection); 570 session->ns_eof = TRUE; 571 (void) cond_broadcast(&nlp->nlp_cv); 572 (void) mutex_unlock(&nlp->nlp_mtx); 573 } 574 575 /* 576 * ************************************************************************ 577 * NDMP V4 HANDLERS 578 * ************************************************************************ 579 */ 580 581 /* 582 * ************************************************************************ 583 * LOCALS 584 * ************************************************************************ 585 */ 586 587 /* 588 * create_md5_digest 589 * 590 * This function uses the MD5 message-digest algorithm described 591 * in RFC1321 to authenticate the client using a shared secret (password). 592 * The message used to compute the MD5 digest is a concatenation of password, 593 * null padding, the 64 byte fixed length challenge and a repeat of the 594 * password. The length of the null padding is chosen to result in a 128 byte 595 * fixed length message. The lengh of the padding can be computed as 596 * 64 - 2*(length of the password). The client digest is computed using the 597 * server challenge from the NDMP_CONFIG_GET_AUTH_ATTR reply. 598 * 599 * Parameters: 600 * digest (output) - 16 bytes MD5 digest 601 * passwd (input) - user password 602 * challenge (input) - 64 bytes server challenge 603 * 604 * Returns: 605 * void 606 */ 607 static void 608 create_md5_digest(unsigned char *digest, char *passwd, unsigned char *challenge) 609 { 610 char buf[130]; 611 char *p = &buf[0]; 612 int len, i; 613 MD5_CTX md; 614 char *pwd; 615 616 *p = 0; 617 pwd = passwd; 618 if ((len = strlen(pwd)) > MD5_PASS_LIMIT) 619 len = MD5_PASS_LIMIT; 620 (void) memcpy(p, pwd, len); 621 p += len; 622 623 for (i = 0; i < MD5_CHALLENGE_SIZE - 2 * len; i++) 624 *p++ = 0; 625 626 (void) memcpy(p, challenge, MD5_CHALLENGE_SIZE); 627 p += MD5_CHALLENGE_SIZE; 628 (void) strlcpy(p, pwd, MD5_PASS_LIMIT); 629 630 MD5Init(&md); 631 MD5Update(&md, buf, 128); 632 MD5Final(digest, &md); 633 } 634 635 /* 636 * ndmp_connect_list_find 637 * 638 * Find the element in the active connection list. 639 * 640 * Parameters: 641 * connection (input) - connection handler. 642 * 643 * Returns: 644 * NULL - error 645 * connection list element pointer 646 */ 647 static struct conn_list * 648 ndmp_connect_list_find(ndmp_connection_t *connection) 649 { 650 struct conn_list *clp; 651 652 NDMP_LOG(LOG_DEBUG, "connection: 0x%p", 653 connection); 654 655 LIST_FOREACH(clp, &cl_head, cl_q) { 656 if (clp->cl_conn == connection) { 657 (void) mutex_unlock(&cl_mutex); 658 return (clp); 659 } 660 } 661 return (NULL); 662 } 663 664 /* 665 * ndmpconnect_list_add 666 * 667 * Add the new connection to the list of the active connections. 668 * 669 * Parameters: 670 * connection (input) - connection handler. 671 * id (input/output) - pointer to connection id. 672 * 673 * Returns: 674 * 0 - success 675 * -1 - error 676 */ 677 int 678 ndmp_connect_list_add(ndmp_connection_t *connection, int *id) 679 { 680 struct conn_list *clp; 681 682 if (connection == NULL) { 683 NDMP_LOG(LOG_DEBUG, "Invalid argument"); 684 return (-1); 685 } 686 687 if ((clp = ndmp_malloc(sizeof (struct conn_list))) == NULL) 688 return (-1); 689 690 clp->cl_conn = connection; 691 clp->cl_id = *id; 692 693 (void) mutex_lock(&cl_mutex); 694 LIST_INSERT_HEAD(&cl_head, clp, cl_q); 695 (*id)++; 696 (void) mutex_unlock(&cl_mutex); 697 698 return (0); 699 } 700 701 /* 702 * ndmp_connect_list_del 703 * 704 * Delete the specified connection from the list. 705 * 706 * Parameters: 707 * connection (input) - connection handler. 708 * 709 * Returns: 710 * 0 - success 711 * -1 - error 712 */ 713 int 714 ndmp_connect_list_del(ndmp_connection_t *connection) 715 { 716 struct conn_list *clp; 717 718 (void) mutex_lock(&cl_mutex); 719 if (!(clp = ndmp_connect_list_find(connection))) { 720 (void) mutex_unlock(&cl_mutex); 721 NDMP_LOG(LOG_DEBUG, "connection not found"); 722 return (-1); 723 } 724 725 LIST_REMOVE(clp, cl_q); 726 (void) mutex_unlock(&cl_mutex); 727 free(clp); 728 729 return (0); 730 } 731 732 733 /* 734 * ndmpconnect_list_find_id 735 * 736 * Find the element specified by its id in the list of active connections. 737 * 738 * Parameters: 739 * id (input) - connection id. 740 * 741 * Returns: 742 * NULL - error 743 * connection list element pointer 744 */ 745 static struct conn_list * 746 ndmp_connect_list_find_id(int id) 747 { 748 struct conn_list *clp; 749 750 NDMP_LOG(LOG_DEBUG, "id: %d", id); 751 752 (void) mutex_lock(&cl_mutex); 753 LIST_FOREACH(clp, &cl_head, cl_q) { 754 if (clp->cl_id == id) { 755 (void) mutex_unlock(&cl_mutex); 756 return (clp); 757 } 758 } 759 760 (void) mutex_unlock(&cl_mutex); 761 return (NULL); 762 } 763 764 /* 765 * Get common fields of the active connection. 766 */ 767 static void 768 ndmp_connect_get_conn(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx) 769 { 770 int port; 771 struct in_addr addr; 772 char cl_addr[NDMP_CL_ADDR_LEN]; 773 ndmpd_session_t *session; 774 775 if (!(session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn))) 776 return; 777 778 ndmp_door_put_int32(enc_ctx, clp->cl_id); 779 ndmp_door_put_int32(enc_ctx, session->ns_protocol_version); 780 ndmp_door_put_int32(enc_ctx, clp->cl_conn->conn_authorized); 781 ndmp_door_put_int32(enc_ctx, session->ns_eof); 782 if (tcp_get_peer(clp->cl_conn->conn_sock, &(addr.s_addr), &port) != -1) 783 (void) snprintf(cl_addr, NDMP_CL_ADDR_LEN, "%s:%d", 784 (char *)inet_ntoa(addr), port); 785 else 786 cl_addr[0] = '\0'; 787 ndmp_door_put_string(enc_ctx, cl_addr); 788 } 789 790 /* 791 * Get the connection SCSI info. 792 */ 793 static void 794 ndmp_connect_get_scsi_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 795 { 796 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_is_open); 797 ndmp_door_put_string(enc_ctx, session->ns_scsi.sd_adapter_name); 798 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_valid_target_set); 799 if (session->ns_scsi.sd_valid_target_set) { 800 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_sid); 801 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_lun); 802 } 803 } 804 805 /* 806 * Get the connection tape info. 807 */ 808 static void 809 ndmp_connect_get_tape_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 810 { 811 char dev_name[NDMP_TAPE_DEV_NAME]; 812 813 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_fd); 814 if (session->ns_tape.td_fd != -1) { 815 ndmp_door_put_uint64(enc_ctx, session->ns_tape.td_record_count); 816 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_mode); 817 (void) snprintf(dev_name, NDMP_TAPE_DEV_NAME, "%st%02x%x", 818 session->ns_tape.td_adapter_name, session->ns_tape.td_sid, 819 session->ns_tape.td_lun); 820 ndmp_door_put_string(enc_ctx, dev_name); 821 ndmp_door_put_string(enc_ctx, session->ns_tape.td_adapter_name); 822 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_sid); 823 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_lun); 824 } 825 } 826 827 /* 828 * Get the connection mover info. 829 */ 830 static void 831 ndmp_connect_get_mover_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 832 { 833 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_state); 834 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_mode); 835 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_pause_reason); 836 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_halt_reason); 837 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_record_size); 838 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_record_num); 839 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_position); 840 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_window_offset); 841 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_window_length); 842 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_sock); 843 } 844 845 /* 846 * Get the connection common data info. 847 */ 848 static void 849 ndmp_connect_get_data_common(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 850 { 851 int i; 852 ndmp_pval *ep; 853 int len; 854 855 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_operation); 856 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_state); 857 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_halt_reason); 858 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_sock); 859 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_mover.addr_type); 860 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_abort); 861 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_read_offset); 862 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_read_length); 863 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_data_size); 864 /* verify data.env has as much data as in session->ns_data.dd_env_len */ 865 len = 0; 866 ep = session->ns_data.dd_env; 867 for (i = 0; ep && i < session->ns_data.dd_env_len; i++, ep++) 868 len++; 869 870 /* put the len */ 871 (void) mutex_lock(&session->ns_lock); 872 ndmp_door_put_uint64(enc_ctx, len); 873 ep = session->ns_data.dd_env; 874 for (i = 0; i < len; i++, ep++) { 875 ndmp_door_put_string(enc_ctx, ep->name); 876 ndmp_door_put_string(enc_ctx, ep->value); 877 } 878 (void) mutex_unlock(&session->ns_lock); 879 } 880 881 /* 882 * Get the connection data info. 883 */ 884 static void 885 ndmp_connect_get_data_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 886 { 887 int i; 888 ndmp_name *np; 889 char tcp_addr[NDMP_TCP_ADDR_SIZE]; 890 891 ndmp_connect_get_data_common(session, enc_ctx); 892 893 switch (session->ns_data.dd_mover.addr_type) { 894 case NDMP_ADDR_LOCAL: 895 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s", "Local"); 896 ndmp_door_put_string(enc_ctx, tcp_addr); 897 break; 898 case NDMP_ADDR_TCP: 899 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d", 900 (char *)inet_ntoa(IN_ADDR( 901 session->ns_data.dd_mover.ndmp_mover_addr_u.addr.ip_addr)), 902 session->ns_data.dd_mover.ndmp_mover_addr_u.addr.port); 903 ndmp_door_put_string(enc_ctx, tcp_addr); 904 break; 905 default: 906 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s", "Unknown"); 907 ndmp_door_put_string(enc_ctx, tcp_addr); 908 } 909 910 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_nlist_len); 911 np = session->ns_data.dd_nlist; 912 for (i = 0; np && i < (int)session->ns_data.dd_nlist_len; i++, np++) { 913 ndmp_door_put_string(enc_ctx, np->name); 914 ndmp_door_put_string(enc_ctx, np->dest); 915 } 916 } 917 918 /* 919 * Get V2 connection info. 920 */ 921 static void 922 ndmp_connect_get_v2(ndmp_connection_t *connection, ndmp_door_ctx_t *enc_ctx) 923 { 924 ndmpd_session_t *session; 925 926 if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) { 927 ndmp_connect_get_scsi_v2(session, enc_ctx); 928 ndmp_connect_get_tape_v2(session, enc_ctx); 929 ndmp_connect_get_mover_v2(session, enc_ctx); 930 ndmp_connect_get_data_v2(session, enc_ctx); 931 } 932 } 933 934 /* 935 * Get the V3 connection mover info. 936 */ 937 static void 938 ndmp_connect_get_mover_v3(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 939 { 940 char tcp_addr[NDMP_TCP_ADDR_SIZE]; 941 942 /* get all the V2 mover data first */ 943 ndmp_connect_get_mover_v2(session, enc_ctx); 944 945 /* get the V3 mover data now */ 946 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_listen_sock); 947 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_data_addr.addr_type); 948 tcp_addr[0] = '\0'; 949 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d", 950 (char *) 951 inet_ntoa(IN_ADDR(session->ns_mover.md_data_addr.tcp_ip_v3)), 952 (int)session->ns_mover.md_data_addr.tcp_port_v3); 953 ndmp_door_put_string(enc_ctx, tcp_addr); 954 } 955 956 /* 957 * Get the connection data info. 958 */ 959 static void 960 ndmp_connect_get_data_v3(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 961 { 962 ulong_t i; 963 mem_ndmp_name_v3_t *np; 964 char tcp_addr[NDMP_TCP_ADDR_SIZE]; 965 966 ndmp_connect_get_data_common(session, enc_ctx); 967 968 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d", 969 (char *)inet_ntoa(IN_ADDR(session->ns_data.dd_data_addr.tcp_ip_v3)), 970 (int)session->ns_data.dd_data_addr.tcp_port_v3); 971 ndmp_door_put_string(enc_ctx, tcp_addr); 972 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_listen_sock); 973 ndmp_door_put_uint64(enc_ctx, 974 session->ns_data.dd_module.dm_stats.ms_bytes_processed); 975 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_nlist_len); 976 np = session->ns_data.dd_nlist_v3; 977 for (i = 0; np && i < (int)session->ns_data.dd_nlist_len; i++, np++) { 978 ndmp_door_put_string(enc_ctx, np->nm3_opath); 979 ndmp_door_put_string(enc_ctx, np->nm3_dpath); 980 ndmp_door_put_uint64(enc_ctx, np->nm3_node); 981 ndmp_door_put_uint64(enc_ctx, np->nm3_fh_info); 982 } 983 } 984 985 /* 986 * Get V3 connection info. 987 */ 988 static void 989 ndmp_connect_get_v3(ndmp_connection_t *connection, ndmp_door_ctx_t *enc_ctx) 990 { 991 ndmpd_session_t *session; 992 993 if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) { 994 ndmp_connect_get_scsi_v2(session, enc_ctx); 995 ndmp_connect_get_tape_v2(session, enc_ctx); 996 ndmp_connect_get_mover_v3(session, enc_ctx); 997 ndmp_connect_get_data_v3(session, enc_ctx); 998 } 999 } 1000 1001 /* 1002 * Get the list of all active sessions to the clients. For each version, 1003 * call the appropriate get function. 1004 */ 1005 static void 1006 connection_get(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx) 1007 { 1008 ndmpd_session_t *session; 1009 1010 session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn); 1011 if (!session) { 1012 ndmp_door_put_int32(enc_ctx, NDMP_SESSION_NODATA); 1013 return; 1014 } 1015 ndmp_door_put_int32(enc_ctx, NDMP_SESSION_DATA); 1016 1017 switch (session->ns_protocol_version) { 1018 case NDMPV2: 1019 ndmp_connect_get_conn(clp, enc_ctx); 1020 ndmp_connect_get_v2(clp->cl_conn, enc_ctx); 1021 break; 1022 case NDMPV3: 1023 case NDMPV4: 1024 ndmp_connect_get_conn(clp, enc_ctx); 1025 ndmp_connect_get_v3(clp->cl_conn, enc_ctx); 1026 break; 1027 default: 1028 NDMP_LOG(LOG_DEBUG, 1029 "Invalid session (0x%p) version 0x%x", session, 1030 session->ns_protocol_version); 1031 } 1032 } 1033 1034 /* 1035 * ndmpd_connect_kill 1036 * 1037 * Kill the connection based on its version. 1038 * 1039 * Parameters: 1040 * connection (input) - connection handler. 1041 * 1042 * Returns: 1043 * 0 - success 1044 * -1 - error 1045 */ 1046 int 1047 ndmpd_connect_kill(ndmp_connection_t *connection) 1048 { 1049 ndmpd_session_t *session; 1050 1051 if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection))) 1052 return (-1); 1053 1054 switch (session->ns_protocol_version) { 1055 case NDMPV2: 1056 ndmpd_connect_close_v2(connection, (void *)NULL); 1057 break; 1058 case NDMPV3: 1059 case NDMPV4: 1060 ndmpd_connect_close_v3(connection, (void *)NULL); 1061 break; 1062 default: 1063 NDMP_LOG(LOG_DEBUG, 1064 "Invalid session (0x%p) version 0x%x", session, 1065 session->ns_protocol_version); 1066 } 1067 1068 return (0); 1069 } 1070 1071 /* 1072 * Get the list of all active sessions to the clients. 1073 */ 1074 void 1075 ndmp_connect_list_get(ndmp_door_ctx_t *enc_ctx) 1076 { 1077 int n; 1078 struct conn_list *clp; 1079 1080 n = 0; 1081 (void) mutex_lock(&cl_mutex); 1082 LIST_FOREACH(clp, &cl_head, cl_q) { 1083 n++; 1084 } 1085 /* write number of connections */ 1086 ndmp_door_put_int32(enc_ctx, n); 1087 n = 0; 1088 LIST_FOREACH(clp, &cl_head, cl_q) { 1089 connection_get(clp, enc_ctx); 1090 n++; 1091 } 1092 (void) mutex_unlock(&cl_mutex); 1093 } 1094 1095 /* 1096 * ndmpd_connect_kill_id 1097 * 1098 * Find a connection by its id and kill it. 1099 * 1100 * Parameters: 1101 * id (input) - connection id. 1102 * 1103 * Returns: 1104 * 0 - success 1105 * -1 - error 1106 */ 1107 int 1108 ndmpd_connect_kill_id(int id) 1109 { 1110 struct conn_list *clp; 1111 1112 if (!(clp = ndmp_connect_list_find_id(id))) 1113 return (-1); 1114 1115 return (ndmpd_connect_kill(clp->cl_conn)); 1116 } 1117 1118 /* Get the devices info */ 1119 void 1120 ndmpd_get_devs(ndmp_door_ctx_t *enc_ctx) 1121 { 1122 int i, n; 1123 sasd_drive_t *sd; 1124 scsi_link_t *slink; 1125 1126 if ((n = sasd_dev_count()) == 0) { 1127 ndmp_door_put_int32(enc_ctx, n); 1128 NDMP_LOG(LOG_DEBUG, "No device attached."); 1129 return; 1130 } 1131 ndmp_door_put_int32(enc_ctx, n); 1132 1133 for (i = 0; i < n; i++) { 1134 sd = sasd_drive(i); 1135 slink = sasd_dev_slink(i); 1136 1137 ndmp_door_put_int32(enc_ctx, slink->sl_type); 1138 ndmp_door_put_string(enc_ctx, sd->sd_name); 1139 ndmp_door_put_int32(enc_ctx, slink->sl_lun); 1140 ndmp_door_put_int32(enc_ctx, slink->sl_sid); 1141 ndmp_door_put_string(enc_ctx, sd->sd_vendor); 1142 ndmp_door_put_string(enc_ctx, sd->sd_id); 1143 ndmp_door_put_string(enc_ctx, sd->sd_rev); 1144 ndmp_door_put_string(enc_ctx, sd->sd_serial); 1145 ndmp_door_put_string(enc_ctx, sd->sd_wwn); 1146 } 1147 } 1148 1149 /* 1150 * ndmpd_connect_auth_text 1151 * 1152 * Checks text authorization. 1153 * 1154 * Parameters: 1155 * auth_id (input) - user name 1156 * auth_password(input) - password 1157 * 1158 * Returns: 1159 * NDMP_NO_ERR: on success 1160 * Other NDMP_ error: invalid user name and password 1161 */ 1162 int 1163 ndmpd_connect_auth_text(char *uname, char *auth_id, char *auth_password) 1164 { 1165 char *passwd, *dec_passwd; 1166 int rv; 1167 1168 if (strcmp(uname, auth_id) != 0) { 1169 rv = NDMP_NOT_AUTHORIZED_ERR; 1170 } else { 1171 passwd = ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD); 1172 if (!passwd || !*passwd) { 1173 rv = NDMP_NOT_AUTHORIZED_ERR; 1174 } else { 1175 dec_passwd = ndmp_base64_decode(passwd); 1176 if (dec_passwd == NULL || *dec_passwd == 0) 1177 rv = NDMP_NOT_AUTHORIZED_ERR; 1178 else if (strcmp(auth_password, dec_passwd) != 0) 1179 rv = NDMP_NOT_AUTHORIZED_ERR; 1180 else 1181 rv = NDMP_NO_ERR; 1182 1183 free(dec_passwd); 1184 } 1185 } 1186 1187 if (rv == NDMP_NO_ERR) { 1188 NDMP_LOG(LOG_DEBUG, "Authorization granted."); 1189 } else { 1190 NDMP_LOG(LOG_ERR, "Authorization denied."); 1191 } 1192 1193 return (rv); 1194 } 1195 1196 1197 /* 1198 * ndmpd_connect_auth_md5 1199 * 1200 * Checks MD5 authorization. 1201 * 1202 * Parameters: 1203 * auth_id (input) - user name 1204 * auth_digest(input) - MD5 digest 1205 * This is a 16 bytes digest info which is a MD5 transform of 128 bytes 1206 * message (password + padding + server challenge + password). Server 1207 * challenge is a 64 bytes random string per NDMP session sent out to the 1208 * client on demand (See NDMP_CONFIG_GET_AUTH_ATTR command). 1209 * 1210 * Returns: 1211 * NDMP_NO_ERR: on success 1212 * Other NDMP_ error: invalid user name and password 1213 */ 1214 int 1215 ndmpd_connect_auth_md5(char *uname, char *auth_id, char *auth_digest, 1216 unsigned char *auth_challenge) 1217 { 1218 char *passwd, *dec_passwd; 1219 unsigned char digest[16]; 1220 int rv; 1221 1222 if (strcmp(uname, auth_id) != 0) { 1223 rv = NDMP_NOT_AUTHORIZED_ERR; 1224 } else { 1225 passwd = ndmpd_get_prop(NDMP_CRAM_MD5_PASSWORD); 1226 if (passwd == NULL || *passwd == 0) { 1227 rv = NDMP_NOT_AUTHORIZED_ERR; 1228 } else { 1229 dec_passwd = ndmp_base64_decode(passwd); 1230 1231 if (dec_passwd == NULL || *dec_passwd == 0) { 1232 rv = NDMP_NOT_AUTHORIZED_ERR; 1233 } else { 1234 create_md5_digest(digest, dec_passwd, 1235 auth_challenge); 1236 if (memcmp(digest, auth_digest, 1237 sizeof (digest)) != 0) { 1238 rv = NDMP_NOT_AUTHORIZED_ERR; 1239 } else { 1240 rv = NDMP_NO_ERR; 1241 } 1242 } 1243 free(dec_passwd); 1244 } 1245 } 1246 1247 if (rv == NDMP_NO_ERR) { 1248 NDMP_LOG(LOG_DEBUG, "Authorization granted."); 1249 } else { 1250 NDMP_LOG(LOG_ERR, "Authorization denied."); 1251 } 1252 1253 return (rv); 1254 } 1255