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