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);
 
 
 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 
 
 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 
 
 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  * ************************************************************************
 
 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;
 
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++;
 
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 
 
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:
 
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 }
 | 
   1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 /*
   6  * BSD 3 Clause License
   7  *
   8  * Copyright (c) 2007, The Storage Networking Industry Association.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  *      - Redistributions of source code must retain the above copyright
  14  *        notice, this list of conditions and the following disclaimer.
  15  *
  16  *      - Redistributions in binary form must reproduce the above copyright
  17  *        notice, this list of conditions and the following disclaimer in
  18  *        the documentation and/or other materials provided with the
  19  *        distribution.
  20  *
  21  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  22  *        nor the names of its contributors may be used to endorse or promote
  23  *        products derived from this software without specific prior written
  24  *        permission.
  25  *
  26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36  * POSSIBILITY OF SUCH DAMAGE.
  37  */
  38 /* Copyright (c) 2007, The Storage Networking Industry Association. */
  39 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
  40 /* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
  41 
  42 #include <sys/types.h>
  43 #include <errno.h>
  44 #include <pwd.h>
  45 #include <syslog.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);
 
 
 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_set_version(connection, request->protocol_version);
 170                 session->ns_protocol_version = request->protocol_version;
 171         }
 172 }
 173 
 174 
 175 /*
 176  * ndmpd_connect_client_auth_v2
 177  *
 178  * This handler authorizes the NDMP connection.
 179  *
 180  * Parameters:
 181  *   connection (input) - connection handle.
 182  *   msginfo    (input) - request message.
 183  *
 184  * Returns:
 185  *   void
 186  */
 187 void
 188 ndmpd_connect_client_auth_v2(ndmp_connection_t *connection, void *body)
 189 {
 190         ndmp_connect_client_auth_request *request;
 191         ndmp_connect_client_auth_reply reply;
 192         ndmp_auth_text *auth;
 193         ndmpd_session_t *session;
 194         ndmp_auth_md5 *md5;
 195         unsigned char md5_digest[16];
 196         char *passwd, *dec_passwd;
 197         char *uname;
 198 
 199         request = (ndmp_connect_client_auth_request *)body;
 200 
 201         reply.error = NDMP_NO_ERR;
 202 
 203         switch (request->auth_data.auth_type) {
 204         case NDMP_AUTH_NONE:
 205                 /*
 206                  * Allow no authorization for development.
 207                  * Comment the following for a non-secure production server.
 208                  */
 209                 syslog(LOG_ERR, "Authorization denied.");
 210                 syslog(LOG_ERR,
 211                     "Authorization type should be md5 or cleartext.");
 212                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
 213                 ndmpd_audit_connect(connection, EINVAL);
 214                 break;
 215 
 216         case NDMP_AUTH_TEXT:
 217                 /* Check authorization.  */
 218                 if ((uname = ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME)) == NULL ||
 219                     *uname == 0) {
 220                         syslog(LOG_ERR, "Authorization denied.");
 221                         syslog(LOG_ERR, "User name is not set at server.");
 222                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 223                         ndmp_set_authorized(connection, FALSE);
 224                         ndmp_send_reply(connection, (void *) &reply,
 225                             "sending ndmp_connect_client_auth reply");
 226                         ndmpd_audit_connect(connection,
 227                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 228                         return;
 229                 }
 230                 auth = &request->auth_data.ndmp_auth_data_u.auth_text;
 231                 if (strcmp(uname, auth->user) != 0) {
 232                         syslog(LOG_ERR,
 233                             "Authorization denied. Not a valid user.");
 234                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 235                         ndmpd_audit_connect(connection,
 236                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 237                         break;
 238                 }
 239                 passwd = ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD);
 240                 if (!passwd || !*passwd) {
 241                         syslog(LOG_ERR, "Authorization denied.");
 242                         syslog(LOG_ERR,
 243                             "Cleartext password is not set at server.");
 244                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 245                         ndmp_set_authorized(connection, FALSE);
 246                         ndmp_send_reply(connection, (void *) &reply,
 247                             "sending ndmp_connect_client_auth reply");
 248                         ndmpd_audit_connect(connection,
 249                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 250                         return;
 251                 } else {
 252                         dec_passwd = ndmp_base64_decode(passwd);
 253                 }
 254                 if (!dec_passwd || !*dec_passwd ||
 255                     strcmp(auth->password, dec_passwd) != 0) {
 256                         syslog(LOG_ERR,
 257                             "Authorization denied. Invalid password.");
 258                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 259                 }
 260                 ndmpd_audit_connect(connection, reply.error ?
 261                     ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
 262 
 263                 free(dec_passwd);
 264                 break;
 265 
 266         case NDMP_AUTH_MD5:
 267                 /* Check authorization.  */
 268                 if ((uname = ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME)) == NULL ||
 269                     *uname == 0) {
 270                         syslog(LOG_ERR, "Authorization denied.");
 271                         syslog(LOG_ERR,  "User name is not set at server.");
 272                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 273                         ndmp_set_authorized(connection, FALSE);
 274                         ndmp_send_reply(connection, (void *) &reply,
 275                             "sending ndmp_connect_client_auth reply");
 276                         ndmpd_audit_connect(connection,
 277                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 278                         return;
 279                 }
 280                 md5 = &request->auth_data.ndmp_auth_data_u.auth_md5;
 281                 passwd = ndmpd_get_prop(NDMP_CRAM_MD5_PASSWORD);
 282                 if (!passwd || !*passwd) {
 283                         syslog(LOG_ERR, "Authorization denied.");
 284                         syslog(LOG_ERR, "MD5 password is not set at server.");
 285                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 286                         ndmp_set_authorized(connection, FALSE);
 287                         ndmp_send_reply(connection, (void *) &reply,
 288                             "sending ndmp_connect_client_auth reply");
 289                         ndmpd_audit_connect(connection,
 290                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 291                         return;
 292                 } else {
 293                         dec_passwd = ndmp_base64_decode(passwd);
 294                 }
 295                 session = ndmp_get_client_data(connection);
 296                 create_md5_digest(md5_digest, dec_passwd,
 297                     session->ns_challenge);
 298 
 299                 if (strcmp(uname, md5->user) != 0) {
 300                         syslog(LOG_ERR,
 301                             "Authorization denied. Not a valid user.");
 302                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 303                 } else if (memcmp(md5_digest, md5->auth_digest,
 304                     sizeof (md5_digest)) != 0) {
 305                         syslog(LOG_ERR,
 306                             "Authorization denied. Invalid password.");
 307                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 308                 }
 309                 ndmpd_audit_connect(connection, reply.error ?
 310                     ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
 311 
 312                 free(dec_passwd);
 313                 break;
 314 
 315         default:
 316                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
 317         }
 318 
 319         if (reply.error == NDMP_NO_ERR)
 320                 ndmp_set_authorized(connection, TRUE);
 321         else
 322                 ndmp_set_authorized(connection, FALSE);
 323 
 324         ndmp_send_reply(connection, (void *) &reply,
 325             "sending ndmp_connect_client_auth reply");
 326 }
 327 
 
 329 /*
 330  * ndmpd_connect_server_auth_v2
 331  *
 332  * This handler authenticates the server to the client.
 333  *
 334  * Parameters:
 335  *   connection (input) - connection handle.
 336  *   msginfo    (input) - request message.
 337  *
 338  * Returns:
 339  *   void
 340  */
 341 void
 342 ndmpd_connect_server_auth_v2(ndmp_connection_t *connection, void *body)
 343 {
 344         ndmp_connect_server_auth_request *request;
 345         ndmp_connect_server_auth_reply reply;
 346 
 347         request = (ndmp_connect_server_auth_request *)body;
 348 
 349         reply.error = NDMP_NO_ERR;
 350         reply.auth_result.auth_type = request->client_attr.auth_type;
 351         switch (request->client_attr.auth_type) {
 352         case NDMP_AUTH_NONE:
 353                 break;
 354 
 355         case NDMP_AUTH_TEXT:
 356                 reply.auth_result.ndmp_auth_data_u.auth_text.user = "ndmpd";
 357                 reply.auth_result.ndmp_auth_data_u.auth_text.password =
 358                     "ndmpsdk";
 359                 break;
 360 
 361         case NDMP_AUTH_MD5:
 362                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
 363                 break;
 364 
 365         default:
 366                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
 367         }
 368 
 
 409  * Parameters:
 410  *   connection (input) - connection handle.
 411  *   msginfo    (input) - request message.
 412  *
 413  * Returns:
 414  *   void
 415  */
 416 void
 417 ndmpd_connect_client_auth_v3(ndmp_connection_t *connection, void *body)
 418 {
 419         ndmp_connect_client_auth_request_v3 *request;
 420         ndmp_connect_client_auth_reply_v3 reply;
 421         ndmp_auth_text_v3 *auth;
 422         ndmpd_session_t *session;
 423         ndmp_auth_md5_v3 *md5;
 424         struct in_addr addr;
 425         char *uname;
 426         char *type;
 427 
 428         request = (ndmp_connect_client_auth_request_v3 *)body;
 429 
 430         reply.error = NDMP_NO_ERR;
 431 
 432         switch (request->auth_data.auth_type) {
 433         case NDMP_AUTH_NONE:
 434                 type = "none";
 435                 reply.error = NDMP_NOT_SUPPORTED_ERR;
 436                 ndmpd_audit_connect(connection, ENOTSUP);
 437                 break;
 438 
 439         case NDMP_AUTH_TEXT:
 440                 /* Check authorization.  */
 441                 if ((uname = ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME)) == NULL ||
 442                     *uname == 0) {
 443                         syslog(LOG_ERR, "Authorization denied.");
 444                         syslog(LOG_ERR, "User name is not set at server.");
 445                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 446                         ndmp_set_authorized(connection, FALSE);
 447                         ndmp_send_reply(connection, (void *) &reply,
 448                             "sending ndmp_connect_client_auth reply");
 449                         ndmpd_audit_connect(connection,
 450                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 451                         return;
 452                 }
 453                 type = "text";
 454                 auth = &request->auth_data.ndmp_auth_data_v3_u.auth_text;
 455                 reply.error = ndmpd_connect_auth_text(uname, auth->auth_id,
 456                     auth->auth_password);
 457                 ndmpd_audit_connect(connection, reply.error ?
 458                     ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
 459                 break;
 460 
 461         case NDMP_AUTH_MD5:
 462                 /* Check authorization.  */
 463                 if ((uname = ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME)) == NULL ||
 464                     *uname == 0) {
 465                         syslog(LOG_ERR, "Authorization denied.");
 466                         syslog(LOG_ERR, "User name is not set at server.");
 467                         reply.error = NDMP_NOT_AUTHORIZED_ERR;
 468                         ndmp_set_authorized(connection, FALSE);
 469                         ndmp_send_reply(connection, (void *) &reply,
 470                             "sending ndmp_connect_client_auth reply");
 471                         ndmpd_audit_connect(connection,
 472                             ADT_FAIL_PAM + PAM_AUTH_ERR);
 473                         return;
 474                 }
 475                 type = "md5";
 476                 session = ndmp_get_client_data(connection);
 477                 md5 = &request->auth_data.ndmp_auth_data_v3_u.auth_md5;
 478                 reply.error = ndmpd_connect_auth_md5(uname, md5->auth_id,
 479                     md5->auth_digest, session->ns_challenge);
 480                 ndmpd_audit_connect(connection, reply.error ?
 481                     ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
 482                 break;
 483 
 484         default:
 485                 type = "unknown";
 486                 reply.error = NDMP_ILLEGAL_ARGS_ERR;
 487                 ndmpd_audit_connect(connection, EINVAL);
 488         }
 489 
 490         if (reply.error == NDMP_NO_ERR) {
 491                 ndmp_set_authorized(connection, TRUE);
 492         } else {
 493                 ndmp_set_authorized(connection, FALSE);
 494                 if (tcp_get_peer(connection->conn_sock, &addr.s_addr,
 495                     NULL) != -1) {
 496                         syslog(LOG_ERR,
 497                             "Authorization(%s) denied for %s.", type,
 498                             inet_ntoa(IN_ADDR(addr)));
 499                 }
 500         }
 501 
 502         ndmp_send_reply(connection, (void *) &reply,
 503             "sending ndmp_connect_auth reply");
 504 }
 505 
 506 
 507 /*
 508  * ndmpd_connect_close_v3
 509  *
 510  * Close the connection to the DMA.
 511  * Send the SHUTDOWN message before closing the socket connection to the DMA.
 512  *
 513  * Parameters:
 514  *   connection (input) - connection handle.
 515  *   msginfo    (input) - request message.
 516  *
 517  * Returns:
 518  *   void
 519  */
 520 /*ARGSUSED*/
 521 void
 522 ndmpd_connect_close_v3(ndmp_connection_t *connection, void *body)
 523 {
 524         ndmpd_session_t *session;
 525         ndmp_lbr_params_t *nlp;
 526         ndmp_notify_connected_request req;
 527 
 528         if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection)))
 529                 return;
 530         if ((nlp = ndmp_get_nlp(session)) == NULL)
 531                 return;
 532 
 533         /* Send the SHUTDOWN message before closing the connection. */
 534         req.reason = NDMP_SHUTDOWN;
 535         req.protocol_version = session->ns_protocol_version;
 536         req.text_reason = "Connection closed by server.";
 537 
 538         if (ndmp_send_request(connection, NDMP_NOTIFY_CONNECTION_STATUS,
 539             NDMP_NO_ERR, (void *) &req, 0) < 0) {
 540                 syslog(LOG_NOTICE, "Sending connection shutdown notify");
 541                 return;
 542         }
 543 
 544         (void) mutex_lock(&nlp->nlp_mtx);
 545         ndmp_close(connection);
 546         session->ns_eof = TRUE;
 547         (void) cond_broadcast(&nlp->nlp_cv);
 548         (void) mutex_unlock(&nlp->nlp_mtx);
 549 }
 550 
 551 /*
 552  * ************************************************************************
 553  * NDMP V4 HANDLERS
 554  * ************************************************************************
 555  */
 556 
 557 /*
 558  * ************************************************************************
 559  * LOCALS
 560  * ************************************************************************
 
 608         MD5Final(digest, &md);
 609 }
 610 
 611 /*
 612  * ndmp_connect_list_find
 613  *
 614  * Find the element in the active connection list.
 615  *
 616  * Parameters:
 617  *   connection (input) - connection handler.
 618  *
 619  * Returns:
 620  *   NULL - error
 621  *   connection list element pointer
 622  */
 623 static struct conn_list *
 624 ndmp_connect_list_find(ndmp_connection_t *connection)
 625 {
 626         struct conn_list *clp;
 627 
 628         LIST_FOREACH(clp, &cl_head, cl_q) {
 629                 if (clp->cl_conn == connection) {
 630                         (void) mutex_unlock(&cl_mutex);
 631                         return (clp);
 632                 }
 633         }
 634         return (NULL);
 635 }
 636 
 637 /*
 638  * ndmpconnect_list_add
 639  *
 640  * Add the new connection to the list of the active connections.
 641  *
 642  * Parameters:
 643  *   connection (input) - connection handler.
 644  *   id (input/output) - pointer to connection id.
 645  *
 646  * Returns:
 647  *   0 - success
 648  *  -1 - error
 649  */
 650 int
 651 ndmp_connect_list_add(ndmp_connection_t *connection, int *id)
 652 {
 653         struct conn_list *clp;
 654 
 655         if (connection == NULL) {
 656                 syslog(LOG_ERR, "ndmp_connect_list_add: Invalid argument");
 657                 return (-1);
 658         }
 659 
 660         if ((clp = ndmp_malloc(sizeof (struct conn_list))) == NULL)
 661                 return (-1);
 662 
 663         clp->cl_conn = connection;
 664         clp->cl_id = *id;
 665 
 666         (void) mutex_lock(&cl_mutex);
 667         LIST_INSERT_HEAD(&cl_head, clp, cl_q);
 668         (*id)++;
 669         (void) mutex_unlock(&cl_mutex);
 670 
 671         return (0);
 672 }
 673 
 674 /*
 675  * ndmp_connect_list_del
 676  *
 677  * Delete the specified connection from the list.
 678  *
 679  * Parameters:
 680  *   connection (input) - connection handler.
 681  *
 682  * Returns:
 683  *   0 - success
 684  *  -1 - error
 685  */
 686 int
 687 ndmp_connect_list_del(ndmp_connection_t *connection)
 688 {
 689         struct conn_list *clp;
 690 
 691         (void) mutex_lock(&cl_mutex);
 692         if (!(clp = ndmp_connect_list_find(connection))) {
 693                 (void) mutex_unlock(&cl_mutex);
 694                 syslog(LOG_ERR, "ndmp_connect_list_del: connection not found");
 695                 return (-1);
 696         }
 697 
 698         LIST_REMOVE(clp, cl_q);
 699         (void) mutex_unlock(&cl_mutex);
 700         free(clp);
 701 
 702         return (0);
 703 }
 704 
 705 
 706 /*
 707  * ndmpconnect_list_find_id
 708  *
 709  * Find the element specified by its id in the list of active connections.
 710  *
 711  * Parameters:
 712  *   id (input) - connection id.
 713  *
 714  * Returns:
 715  *   NULL - error
 716  *   connection list element pointer
 717  */
 718 static struct conn_list *
 719 ndmp_connect_list_find_id(int id)
 720 {
 721         struct conn_list *clp;
 722 
 723         (void) mutex_lock(&cl_mutex);
 724         LIST_FOREACH(clp, &cl_head, cl_q) {
 725                 if (clp->cl_id == id) {
 726                         (void) mutex_unlock(&cl_mutex);
 727                         return (clp);
 728                 }
 729         }
 730 
 731         (void) mutex_unlock(&cl_mutex);
 732         return (NULL);
 733 }
 734 
 735 /*
 736  * Get common fields of the active connection.
 737  */
 738 static void
 739 ndmp_connect_get_conn(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx)
 740 {
 741         int port;
 742         struct in_addr addr;
 
 979         ndmpd_session_t *session;
 980 
 981         session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn);
 982         if (!session) {
 983                 ndmp_door_put_int32(enc_ctx, NDMP_SESSION_NODATA);
 984                 return;
 985         }
 986         ndmp_door_put_int32(enc_ctx, NDMP_SESSION_DATA);
 987 
 988         switch (session->ns_protocol_version) {
 989         case NDMPV2:
 990                 ndmp_connect_get_conn(clp, enc_ctx);
 991                 ndmp_connect_get_v2(clp->cl_conn, enc_ctx);
 992                 break;
 993         case NDMPV3:
 994         case NDMPV4:
 995                 ndmp_connect_get_conn(clp, enc_ctx);
 996                 ndmp_connect_get_v3(clp->cl_conn, enc_ctx);
 997                 break;
 998         default:
 999                 syslog(LOG_ERR,
1000                     "Invalid session (0x%p) version 0x%x", session,
1001                     session->ns_protocol_version);
1002         }
1003 }
1004 
1005 /*
1006  * ndmpd_connect_kill
1007  *
1008  * Kill the connection based on its version.
1009  *
1010  * Parameters:
1011  *   connection (input) - connection handler.
1012  *
1013  * Returns:
1014  *   0 - success
1015  *  -1 - error
1016  */
1017 int
1018 ndmpd_connect_kill(ndmp_connection_t *connection)
1019 {
1020         ndmpd_session_t *session;
1021 
1022         if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection)))
1023                 return (-1);
1024 
1025         switch (session->ns_protocol_version) {
1026         case NDMPV2:
1027                 ndmpd_connect_close_v2(connection, (void *)NULL);
1028                 break;
1029         case NDMPV3:
1030         case NDMPV4:
1031                 ndmpd_connect_close_v3(connection, (void *)NULL);
1032                 break;
1033         default:
1034                 syslog(LOG_ERR,
1035                     "Invalid session (0x%p) version 0x%x", session,
1036                     session->ns_protocol_version);
1037         }
1038 
1039         return (0);
1040 }
1041 
1042 /*
1043  * Get the list of all active sessions to the clients.
1044  */
1045 void
1046 ndmp_connect_list_get(ndmp_door_ctx_t *enc_ctx)
1047 {
1048         int n;
1049         struct conn_list *clp;
1050 
1051         n = 0;
1052         (void) mutex_lock(&cl_mutex);
1053         LIST_FOREACH(clp, &cl_head, cl_q) {
1054                 n++;
 
1079 ndmpd_connect_kill_id(int id)
1080 {
1081         struct conn_list *clp;
1082 
1083         if (!(clp = ndmp_connect_list_find_id(id)))
1084                 return (-1);
1085 
1086         return (ndmpd_connect_kill(clp->cl_conn));
1087 }
1088 
1089 /* Get the devices info */
1090 void
1091 ndmpd_get_devs(ndmp_door_ctx_t *enc_ctx)
1092 {
1093         int i, n;
1094         sasd_drive_t *sd;
1095         scsi_link_t *slink;
1096 
1097         if ((n = sasd_dev_count()) == 0) {
1098                 ndmp_door_put_int32(enc_ctx, n);
1099                 syslog(LOG_DEBUG, "No device attached.");
1100                 return;
1101         }
1102         ndmp_door_put_int32(enc_ctx, n);
1103 
1104         for (i = 0; i < n; i++) {
1105                 sd = sasd_drive(i);
1106                 slink = sasd_dev_slink(i);
1107 
1108                 ndmp_door_put_int32(enc_ctx, slink->sl_type);
1109                 ndmp_door_put_string(enc_ctx, sd->sd_name);
1110                 ndmp_door_put_int32(enc_ctx, slink->sl_lun);
1111                 ndmp_door_put_int32(enc_ctx, slink->sl_sid);
1112                 ndmp_door_put_string(enc_ctx, sd->sd_vendor);
1113                 ndmp_door_put_string(enc_ctx, sd->sd_id);
1114                 ndmp_door_put_string(enc_ctx, sd->sd_rev);
1115                 ndmp_door_put_string(enc_ctx, sd->sd_serial);
1116                 ndmp_door_put_string(enc_ctx, sd->sd_wwn);
1117         }
1118 }
1119 
 
1138 
1139         if (strcmp(uname, auth_id) != 0) {
1140                 rv = NDMP_NOT_AUTHORIZED_ERR;
1141         } else {
1142                 passwd = ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD);
1143                 if (!passwd || !*passwd) {
1144                         rv = NDMP_NOT_AUTHORIZED_ERR;
1145                 } else {
1146                         dec_passwd = ndmp_base64_decode(passwd);
1147                         if (dec_passwd == NULL || *dec_passwd == 0)
1148                                 rv = NDMP_NOT_AUTHORIZED_ERR;
1149                         else if (strcmp(auth_password, dec_passwd) != 0)
1150                                 rv = NDMP_NOT_AUTHORIZED_ERR;
1151                         else
1152                                 rv = NDMP_NO_ERR;
1153 
1154                         free(dec_passwd);
1155                 }
1156         }
1157 
1158         if (rv != NDMP_NO_ERR) {
1159                 syslog(LOG_ERR, "Authorization denied.");
1160         }
1161 
1162         return (rv);
1163 }
1164 
1165 
1166 /*
1167  * ndmpd_connect_auth_md5
1168  *
1169  * Checks MD5 authorization.
1170  *
1171  * Parameters:
1172  *   auth_id (input) - user name
1173  *   auth_digest(input) - MD5 digest
1174  *      This is a 16 bytes digest info which is a MD5 transform of 128 bytes
1175  *      message (password + padding + server challenge + password). Server
1176  *      challenge is a 64 bytes random string per NDMP session sent out to the
1177  *      client on demand (See NDMP_CONFIG_GET_AUTH_ATTR command).
1178  *
1179  * Returns:
 
1196                         rv = NDMP_NOT_AUTHORIZED_ERR;
1197                 } else {
1198                         dec_passwd = ndmp_base64_decode(passwd);
1199 
1200                         if (dec_passwd == NULL || *dec_passwd == 0) {
1201                                 rv = NDMP_NOT_AUTHORIZED_ERR;
1202                         } else {
1203                                 create_md5_digest(digest, dec_passwd,
1204                                     auth_challenge);
1205                                 if (memcmp(digest, auth_digest,
1206                                     sizeof (digest)) != 0) {
1207                                         rv = NDMP_NOT_AUTHORIZED_ERR;
1208                                 } else {
1209                                         rv = NDMP_NO_ERR;
1210                                 }
1211                         }
1212                         free(dec_passwd);
1213                 }
1214         }
1215 
1216         return (rv);
1217 }
 |