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 /* LINTED: E_CONSTANT_CONDITION */ 688 LIST_INSERT_HEAD(&cl_head, clp, cl_q); 689 (*id)++; 690 (void) mutex_unlock(&cl_mutex); 691 692 return (0); 693 } 694 695 /* 696 * ndmp_connect_list_del 697 * 698 * Delete the specified connection from the list. 699 * 700 * Parameters: 701 * connection (input) - connection handler. 702 * 703 * Returns: 704 * 0 - success 705 * -1 - error 706 */ 707 int 708 ndmp_connect_list_del(ndmp_connection_t *connection) 709 { 710 struct conn_list *clp; 711 712 (void) mutex_lock(&cl_mutex); 713 if (!(clp = ndmp_connect_list_find(connection))) { 714 (void) mutex_unlock(&cl_mutex); 715 NDMP_LOG(LOG_DEBUG, "connection not found"); 716 return (-1); 717 } 718 719 /* LINTED: E_CONSTANT_CONDITION */ 720 LIST_REMOVE(clp, cl_q); 721 (void) mutex_unlock(&cl_mutex); 722 free(clp); 723 724 return (0); 725 } 726 727 728 /* 729 * ndmpconnect_list_find_id 730 * 731 * Find the element specified by its id in the list of active connections. 732 * 733 * Parameters: 734 * id (input) - connection id. 735 * 736 * Returns: 737 * NULL - error 738 * connection list element pointer 739 */ 740 static struct conn_list * 741 ndmp_connect_list_find_id(int id) 742 { 743 struct conn_list *clp; 744 745 NDMP_LOG(LOG_DEBUG, "id: %d", id); 746 747 (void) mutex_lock(&cl_mutex); 748 LIST_FOREACH(clp, &cl_head, cl_q) { 749 if (clp->cl_id == id) { 750 (void) mutex_unlock(&cl_mutex); 751 return (clp); 752 } 753 } 754 755 (void) mutex_unlock(&cl_mutex); 756 return (NULL); 757 } 758 759 /* 760 * Get common fields of the active connection. 761 */ 762 static void 763 ndmp_connect_get_conn(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx) 764 { 765 int port; 766 struct in_addr addr; 767 char cl_addr[NDMP_CL_ADDR_LEN]; 768 ndmpd_session_t *session; 769 770 if (!(session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn))) 771 return; 772 773 ndmp_door_put_int32(enc_ctx, clp->cl_id); 774 ndmp_door_put_int32(enc_ctx, session->ns_protocol_version); 775 ndmp_door_put_int32(enc_ctx, clp->cl_conn->conn_authorized); 776 ndmp_door_put_int32(enc_ctx, session->ns_eof); 777 if (tcp_get_peer(clp->cl_conn->conn_sock, &(addr.s_addr), &port) != -1) 778 (void) snprintf(cl_addr, NDMP_CL_ADDR_LEN, "%s:%d", 779 (char *)inet_ntoa(addr), port); 780 else 781 cl_addr[0] = '\0'; 782 ndmp_door_put_string(enc_ctx, cl_addr); 783 } 784 785 /* 786 * Get the connection SCSI info. 787 */ 788 static void 789 ndmp_connect_get_scsi_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 790 { 791 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_is_open); 792 ndmp_door_put_string(enc_ctx, session->ns_scsi.sd_adapter_name); 793 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_valid_target_set); 794 if (session->ns_scsi.sd_valid_target_set) { 795 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_sid); 796 ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_lun); 797 } 798 } 799 800 /* 801 * Get the connection tape info. 802 */ 803 static void 804 ndmp_connect_get_tape_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 805 { 806 char dev_name[NDMP_TAPE_DEV_NAME]; 807 808 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_fd); 809 if (session->ns_tape.td_fd != -1) { 810 ndmp_door_put_uint64(enc_ctx, session->ns_tape.td_record_count); 811 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_mode); 812 (void) snprintf(dev_name, NDMP_TAPE_DEV_NAME, "%st%02x%x", 813 session->ns_tape.td_adapter_name, session->ns_tape.td_sid, 814 session->ns_tape.td_lun); 815 ndmp_door_put_string(enc_ctx, dev_name); 816 ndmp_door_put_string(enc_ctx, session->ns_tape.td_adapter_name); 817 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_sid); 818 ndmp_door_put_int32(enc_ctx, session->ns_tape.td_lun); 819 } 820 } 821 822 /* 823 * Get the connection mover info. 824 */ 825 static void 826 ndmp_connect_get_mover_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 827 { 828 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_state); 829 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_mode); 830 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_pause_reason); 831 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_halt_reason); 832 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_record_size); 833 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_record_num); 834 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_position); 835 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_window_offset); 836 ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_window_length); 837 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_sock); 838 } 839 840 /* 841 * Get the connection common data info. 842 */ 843 static void 844 ndmp_connect_get_data_common(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 845 { 846 int i; 847 ndmp_pval *ep; 848 int len; 849 850 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_operation); 851 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_state); 852 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_halt_reason); 853 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_sock); 854 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_mover.addr_type); 855 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_abort); 856 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_read_offset); 857 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_read_length); 858 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_data_size); 859 /* verify data.env has as much data as in session->ns_data.dd_env_len */ 860 len = 0; 861 ep = session->ns_data.dd_env; 862 for (i = 0; ep && i < session->ns_data.dd_env_len; i++, ep++) 863 len++; 864 865 /* put the len */ 866 (void) mutex_lock(&session->ns_lock); 867 ndmp_door_put_uint64(enc_ctx, len); 868 ep = session->ns_data.dd_env; 869 for (i = 0; i < len; i++, ep++) { 870 ndmp_door_put_string(enc_ctx, ep->name); 871 ndmp_door_put_string(enc_ctx, ep->value); 872 } 873 (void) mutex_unlock(&session->ns_lock); 874 } 875 876 /* 877 * Get the connection data info. 878 */ 879 static void 880 ndmp_connect_get_data_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 881 { 882 int i; 883 ndmp_name *np; 884 char tcp_addr[NDMP_TCP_ADDR_SIZE]; 885 886 ndmp_connect_get_data_common(session, enc_ctx); 887 888 switch (session->ns_data.dd_mover.addr_type) { 889 case NDMP_ADDR_LOCAL: 890 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s", "Local"); 891 ndmp_door_put_string(enc_ctx, tcp_addr); 892 break; 893 case NDMP_ADDR_TCP: 894 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d", 895 (char *)inet_ntoa(IN_ADDR( 896 session->ns_data.dd_mover.ndmp_mover_addr_u.addr.ip_addr)), 897 session->ns_data.dd_mover.ndmp_mover_addr_u.addr.port); 898 ndmp_door_put_string(enc_ctx, tcp_addr); 899 break; 900 default: 901 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s", "Unknown"); 902 ndmp_door_put_string(enc_ctx, tcp_addr); 903 } 904 905 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_nlist_len); 906 np = session->ns_data.dd_nlist; 907 for (i = 0; np && i < (int)session->ns_data.dd_nlist_len; i++, np++) { 908 ndmp_door_put_string(enc_ctx, np->name); 909 ndmp_door_put_string(enc_ctx, np->dest); 910 } 911 } 912 913 /* 914 * Get V2 connection info. 915 */ 916 static void 917 ndmp_connect_get_v2(ndmp_connection_t *connection, ndmp_door_ctx_t *enc_ctx) 918 { 919 ndmpd_session_t *session; 920 921 if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) { 922 ndmp_connect_get_scsi_v2(session, enc_ctx); 923 ndmp_connect_get_tape_v2(session, enc_ctx); 924 ndmp_connect_get_mover_v2(session, enc_ctx); 925 ndmp_connect_get_data_v2(session, enc_ctx); 926 } 927 } 928 929 /* 930 * Get the V3 connection mover info. 931 */ 932 static void 933 ndmp_connect_get_mover_v3(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 934 { 935 char tcp_addr[NDMP_TCP_ADDR_SIZE]; 936 937 /* get all the V2 mover data first */ 938 ndmp_connect_get_mover_v2(session, enc_ctx); 939 940 /* get the V3 mover data now */ 941 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_listen_sock); 942 ndmp_door_put_int32(enc_ctx, session->ns_mover.md_data_addr.addr_type); 943 tcp_addr[0] = '\0'; 944 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d", 945 (char *) 946 inet_ntoa(IN_ADDR(session->ns_mover.md_data_addr.tcp_ip_v3)), 947 (int)session->ns_mover.md_data_addr.tcp_port_v3); 948 ndmp_door_put_string(enc_ctx, tcp_addr); 949 } 950 951 /* 952 * Get the connection data info. 953 */ 954 static void 955 ndmp_connect_get_data_v3(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx) 956 { 957 ulong_t i; 958 mem_ndmp_name_v3_t *np; 959 char tcp_addr[NDMP_TCP_ADDR_SIZE]; 960 961 ndmp_connect_get_data_common(session, enc_ctx); 962 963 (void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d", 964 (char *)inet_ntoa(IN_ADDR(session->ns_data.dd_data_addr.tcp_ip_v3)), 965 (int)session->ns_data.dd_data_addr.tcp_port_v3); 966 ndmp_door_put_string(enc_ctx, tcp_addr); 967 ndmp_door_put_int32(enc_ctx, session->ns_data.dd_listen_sock); 968 ndmp_door_put_uint64(enc_ctx, 969 session->ns_data.dd_module.dm_stats.ms_bytes_processed); 970 ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_nlist_len); 971 np = session->ns_data.dd_nlist_v3; 972 for (i = 0; np && i < (int)session->ns_data.dd_nlist_len; i++, np++) { 973 ndmp_door_put_string(enc_ctx, np->nm3_opath); 974 ndmp_door_put_string(enc_ctx, np->nm3_dpath); 975 ndmp_door_put_uint64(enc_ctx, np->nm3_node); 976 ndmp_door_put_uint64(enc_ctx, np->nm3_fh_info); 977 } 978 } 979 980 /* 981 * Get V3 connection info. 982 */ 983 static void 984 ndmp_connect_get_v3(ndmp_connection_t *connection, ndmp_door_ctx_t *enc_ctx) 985 { 986 ndmpd_session_t *session; 987 988 if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) { 989 ndmp_connect_get_scsi_v2(session, enc_ctx); 990 ndmp_connect_get_tape_v2(session, enc_ctx); 991 ndmp_connect_get_mover_v3(session, enc_ctx); 992 ndmp_connect_get_data_v3(session, enc_ctx); 993 } 994 } 995 996 /* 997 * Get the list of all active sessions to the clients. For each version, 998 * call the appropriate get function. 999 */ 1000 static void 1001 connection_get(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx) 1002 { 1003 ndmpd_session_t *session; 1004 1005 session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn); 1006 if (!session) { 1007 ndmp_door_put_int32(enc_ctx, NDMP_SESSION_NODATA); 1008 return; 1009 } 1010 ndmp_door_put_int32(enc_ctx, NDMP_SESSION_DATA); 1011 1012 switch (session->ns_protocol_version) { 1013 case NDMPV2: 1014 ndmp_connect_get_conn(clp, enc_ctx); 1015 ndmp_connect_get_v2(clp->cl_conn, enc_ctx); 1016 break; 1017 case NDMPV3: 1018 case NDMPV4: 1019 ndmp_connect_get_conn(clp, enc_ctx); 1020 ndmp_connect_get_v3(clp->cl_conn, enc_ctx); 1021 break; 1022 default: 1023 NDMP_LOG(LOG_DEBUG, 1024 "Invalid session (0x%p) version 0x%x", session, 1025 session->ns_protocol_version); 1026 } 1027 } 1028 1029 /* 1030 * ndmpd_connect_kill 1031 * 1032 * Kill the connection based on its version. 1033 * 1034 * Parameters: 1035 * connection (input) - connection handler. 1036 * 1037 * Returns: 1038 * 0 - success 1039 * -1 - error 1040 */ 1041 int 1042 ndmpd_connect_kill(ndmp_connection_t *connection) 1043 { 1044 ndmpd_session_t *session; 1045 1046 if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection))) 1047 return (-1); 1048 1049 switch (session->ns_protocol_version) { 1050 case NDMPV2: 1051 nlp_event_rv_set(session, -2); 1052 nlp_event_nw(session); 1053 ndmpd_connect_close_v2(connection, (void *)NULL); 1054 break; 1055 case NDMPV3: 1056 case NDMPV4: 1057 nlp_event_rv_set(session, -2); 1058 nlp_event_nw(session); 1059 ndmpd_connect_close_v3(connection, (void *)NULL); 1060 break; 1061 default: 1062 NDMP_LOG(LOG_DEBUG, 1063 "Invalid session (0x%p) version 0x%x", session, 1064 session->ns_protocol_version); 1065 } 1066 1067 return (0); 1068 } 1069 1070 /* 1071 * Get the list of all active sessions to the clients. 1072 */ 1073 void 1074 ndmp_connect_list_get(ndmp_door_ctx_t *enc_ctx) 1075 { 1076 int n; 1077 struct conn_list *clp; 1078 1079 n = 0; 1080 (void) mutex_lock(&cl_mutex); 1081 LIST_FOREACH(clp, &cl_head, cl_q) { 1082 n++; 1083 } 1084 /* write number of connections */ 1085 ndmp_door_put_int32(enc_ctx, n); 1086 n = 0; 1087 LIST_FOREACH(clp, &cl_head, cl_q) { 1088 connection_get(clp, enc_ctx); 1089 n++; 1090 } 1091 (void) mutex_unlock(&cl_mutex); 1092 } 1093 1094 /* 1095 * ndmpd_connect_kill_id 1096 * 1097 * Find a connection by its id and kill it. 1098 * 1099 * Parameters: 1100 * id (input) - connection id. 1101 * 1102 * Returns: 1103 * 0 - success 1104 * -1 - error 1105 */ 1106 int 1107 ndmpd_connect_kill_id(int id) 1108 { 1109 struct conn_list *clp; 1110 1111 if (!(clp = ndmp_connect_list_find_id(id))) 1112 return (-1); 1113 1114 return (ndmpd_connect_kill(clp->cl_conn)); 1115 } 1116 1117 /* Get the devices info */ 1118 void 1119 ndmpd_get_devs(ndmp_door_ctx_t *enc_ctx) 1120 { 1121 int i, n; 1122 sasd_drive_t *sd; 1123 scsi_link_t *slink; 1124 1125 if ((n = sasd_dev_count()) == 0) { 1126 ndmp_door_put_int32(enc_ctx, n); 1127 NDMP_LOG(LOG_DEBUG, "No device attached."); 1128 return; 1129 } 1130 ndmp_door_put_int32(enc_ctx, n); 1131 1132 for (i = 0; i < n; i++) { 1133 sd = sasd_drive(i); 1134 slink = sasd_dev_slink(i); 1135 1136 ndmp_door_put_int32(enc_ctx, slink->sl_type); 1137 ndmp_door_put_string(enc_ctx, sd->sd_name); 1138 ndmp_door_put_int32(enc_ctx, slink->sl_lun); 1139 ndmp_door_put_int32(enc_ctx, slink->sl_sid); 1140 ndmp_door_put_string(enc_ctx, sd->sd_vendor); 1141 ndmp_door_put_string(enc_ctx, sd->sd_id); 1142 ndmp_door_put_string(enc_ctx, sd->sd_rev); 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