12654012fSReza Sabdar /*
22654012fSReza Sabdar  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
32654012fSReza Sabdar  * Use is subject to license terms.
42654012fSReza Sabdar  */
52654012fSReza Sabdar 
62654012fSReza Sabdar /*
72654012fSReza Sabdar  * BSD 3 Clause License
82654012fSReza Sabdar  *
92654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
102654012fSReza Sabdar  *
112654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
122654012fSReza Sabdar  * modification, are permitted provided that the following conditions
132654012fSReza Sabdar  * are met:
142654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
152654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
162654012fSReza Sabdar  *
172654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
182654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
192654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
202654012fSReza Sabdar  *	  distribution.
212654012fSReza Sabdar  *
222654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
232654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
242654012fSReza Sabdar  *	  products derived from this software without specific prior written
252654012fSReza Sabdar  *	  permission.
262654012fSReza Sabdar  *
272654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
282654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
292654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
302654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
312654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
322654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
332654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
342654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
352654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
362654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
372654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
382654012fSReza Sabdar  */
392654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */
402654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
41*a23888a3SJan Kryl /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
422654012fSReza Sabdar 
432654012fSReza Sabdar #include <sys/types.h>
442654012fSReza Sabdar #include <errno.h>
452654012fSReza Sabdar #include <pwd.h>
462654012fSReza Sabdar #include <sys/socket.h>
472654012fSReza Sabdar #include <netinet/in.h>
482654012fSReza Sabdar #include <sys/queue.h>
492654012fSReza Sabdar #include <arpa/inet.h>
502654012fSReza Sabdar #include <md5.h>
512654012fSReza Sabdar #include <shadow.h>
522654012fSReza Sabdar #include <crypt.h>
532654012fSReza Sabdar #include <alloca.h>
542654012fSReza Sabdar #include "ndmpd_common.h"
552654012fSReza Sabdar #include "ndmpd.h"
562654012fSReza Sabdar #include <libndmp.h>
572654012fSReza Sabdar #include <ndmpd_door.h>
582654012fSReza Sabdar #include <security/pam_appl.h>
592654012fSReza Sabdar 
602654012fSReza Sabdar 
612654012fSReza Sabdar static int ndmpd_connect_auth_text(char *uname, char *auth_id,
622654012fSReza Sabdar     char *auth_password);
632654012fSReza Sabdar static int ndmpd_connect_auth_md5(char *uname, char *auth_id, char *auth_digest,
642654012fSReza Sabdar     unsigned char *auth_challenge);
652654012fSReza Sabdar static struct conn_list *ndmp_connect_list_find(ndmp_connection_t *connection);
662654012fSReza Sabdar static void create_md5_digest(unsigned char *digest, char *passwd,
672654012fSReza Sabdar     unsigned char *challenge);
682654012fSReza Sabdar static struct conn_list *ndmp_connect_list_find_id(int id);
692654012fSReza Sabdar 
702654012fSReza Sabdar /* routines for connection info */
712654012fSReza Sabdar void ndmp_connect_list_get(ndmp_door_ctx_t *enc_ctx);
722654012fSReza Sabdar static void connection_get(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx);
732654012fSReza Sabdar static void ndmp_connect_get_conn(struct conn_list *clp,
742654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
752654012fSReza Sabdar static void ndmp_connect_get_v2(ndmp_connection_t *connection,
762654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
772654012fSReza Sabdar static void ndmp_connect_get_scsi_v2(ndmpd_session_t *session,
782654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
792654012fSReza Sabdar static void ndmp_connect_get_tape_v2(ndmpd_session_t *session,
802654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
812654012fSReza Sabdar static void ndmp_connect_get_mover_v2(ndmpd_session_t *session,
822654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
832654012fSReza Sabdar static void ndmp_connect_get_data_v2(ndmpd_session_t *session,
842654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
852654012fSReza Sabdar static void ndmp_connect_get_v3(ndmp_connection_t *connection,
862654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
872654012fSReza Sabdar static void ndmp_connect_get_mover_v3(ndmpd_session_t *session,
882654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
892654012fSReza Sabdar static void ndmp_connect_get_data_v3(ndmpd_session_t *session,
902654012fSReza Sabdar     ndmp_door_ctx_t *enc_ctx);
912654012fSReza Sabdar void ndmpd_get_devs(ndmp_door_ctx_t *enc_ctx);
922654012fSReza Sabdar 
932654012fSReza Sabdar #ifndef LIST_FOREACH
942654012fSReza Sabdar #define	LIST_FOREACH(var, head, field)					\
952654012fSReza Sabdar 	for ((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
962654012fSReza Sabdar #endif /* LIST_FOREACH */
972654012fSReza Sabdar 
982654012fSReza Sabdar /*
992654012fSReza Sabdar  * List of active connections.
1002654012fSReza Sabdar  */
1012654012fSReza Sabdar struct conn_list {
1022654012fSReza Sabdar 	LIST_ENTRY(conn_list) cl_q;
1032654012fSReza Sabdar 	int cl_id;
1042654012fSReza Sabdar 	ndmp_connection_t *cl_conn;
1052654012fSReza Sabdar };
1062654012fSReza Sabdar LIST_HEAD(cl_head, conn_list);
1072654012fSReza Sabdar 
1082654012fSReza Sabdar /*
1092654012fSReza Sabdar  * Head of the active connections.
1102654012fSReza Sabdar  */
1112654012fSReza Sabdar static struct cl_head cl_head;
1122654012fSReza Sabdar 
1132654012fSReza Sabdar mutex_t cl_mutex = DEFAULTMUTEX;
1142654012fSReza Sabdar 
1152654012fSReza Sabdar 
1162654012fSReza Sabdar /*
1172654012fSReza Sabdar  * Set this variable to non-zero to print verbose information.
1182654012fSReza Sabdar  */
1192654012fSReza Sabdar int ndmp_connect_print_verbose = 0;
1202654012fSReza Sabdar 
1212654012fSReza Sabdar 
1222654012fSReza Sabdar /*
1232654012fSReza Sabdar  * ************************************************************************
1242654012fSReza Sabdar  * NDMP V2 HANDLERS
1252654012fSReza Sabdar  * ************************************************************************
1262654012fSReza Sabdar  */
1272654012fSReza Sabdar 
1282654012fSReza Sabdar /*
1292654012fSReza Sabdar  * ndmpd_connect_open_v2
1302654012fSReza Sabdar  *
1312654012fSReza Sabdar  * This handler sets the protocol version to be used on the connection.
1322654012fSReza Sabdar  *
1332654012fSReza Sabdar  * Parameters:
1342654012fSReza Sabdar  *   connection (input) - connection handle.
1352654012fSReza Sabdar  *   body       (input) - request message body.
1362654012fSReza Sabdar  *
1372654012fSReza Sabdar  * Returns:
1382654012fSReza Sabdar  *   void
1392654012fSReza Sabdar  */
1402654012fSReza Sabdar 
1412654012fSReza Sabdar void
ndmpd_connect_open_v2(ndmp_connection_t * connection,void * body)1422654012fSReza Sabdar ndmpd_connect_open_v2(ndmp_connection_t *connection, void *body)
1432654012fSReza Sabdar {
1442654012fSReza Sabdar 	ndmp_connect_open_request *request = (ndmp_connect_open_request *)body;
1452654012fSReza Sabdar 	ndmp_connect_open_reply reply;
1462654012fSReza Sabdar 	ndmpd_session_t *session;
1472654012fSReza Sabdar 
1482654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
1492654012fSReza Sabdar 
1502654012fSReza Sabdar 	if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection)))
1512654012fSReza Sabdar 		return;
1522654012fSReza Sabdar 
1532654012fSReza Sabdar 	if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE ||
1542654012fSReza Sabdar 	    session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
1552654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
1562654012fSReza Sabdar 	else if (request->protocol_version > ndmp_ver)
1572654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
1582654012fSReza Sabdar 
1592654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
1602654012fSReza Sabdar 	    "sending connect_open reply");
1612654012fSReza Sabdar 
1622654012fSReza Sabdar 	/*
1632654012fSReza Sabdar 	 * Set the protocol version.
1642654012fSReza Sabdar 	 * Must wait until after sending the reply since the reply
1652654012fSReza Sabdar 	 * must be sent using the same protocol version that was used
1662654012fSReza Sabdar 	 * to process the request.
1672654012fSReza Sabdar 	 */
1682654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR) {
1692654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "set ver to: %d",
1702654012fSReza Sabdar 		    request->protocol_version);
1712654012fSReza Sabdar 		ndmp_set_version(connection, request->protocol_version);
1722654012fSReza Sabdar 		session->ns_protocol_version = request->protocol_version;
1732654012fSReza Sabdar 	}
1742654012fSReza Sabdar }
1752654012fSReza Sabdar 
1762654012fSReza Sabdar 
1772654012fSReza Sabdar /*
1782654012fSReza Sabdar  * ndmpd_connect_client_auth_v2
1792654012fSReza Sabdar  *
1802654012fSReza Sabdar  * This handler authorizes the NDMP connection.
1812654012fSReza Sabdar  *
1822654012fSReza Sabdar  * Parameters:
1832654012fSReza Sabdar  *   connection (input) - connection handle.
1842654012fSReza Sabdar  *   msginfo    (input) - request message.
1852654012fSReza Sabdar  *
1862654012fSReza Sabdar  * Returns:
1872654012fSReza Sabdar  *   void
1882654012fSReza Sabdar  */
1892654012fSReza Sabdar void
ndmpd_connect_client_auth_v2(ndmp_connection_t * connection,void * body)1902654012fSReza Sabdar ndmpd_connect_client_auth_v2(ndmp_connection_t *connection, void *body)
1912654012fSReza Sabdar {
1922654012fSReza Sabdar 	ndmp_connect_client_auth_request *request;
1932654012fSReza Sabdar 	ndmp_connect_client_auth_reply reply;
1942654012fSReza Sabdar 	ndmp_auth_text *auth;
1952654012fSReza Sabdar 	ndmpd_session_t *session;
1962654012fSReza Sabdar 	ndmp_auth_md5 *md5;
1972654012fSReza Sabdar 	unsigned char md5_digest[16];
1982654012fSReza Sabdar 	char *passwd, *dec_passwd;
1992654012fSReza Sabdar 	char *uname;
2002654012fSReza Sabdar 
2012654012fSReza Sabdar 	request = (ndmp_connect_client_auth_request *)body;
2022654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "auth_type:%s",
2032654012fSReza Sabdar 	    request->auth_data.auth_type == NDMP_AUTH_NONE ? "None" :
2042654012fSReza Sabdar 	    (request->auth_data.auth_type == NDMP_AUTH_TEXT ? "Text" :
2052654012fSReza Sabdar 	    (request->auth_data.auth_type == NDMP_AUTH_MD5 ? "MD5" :
2062654012fSReza Sabdar 	    "Invalid")));
2072654012fSReza Sabdar 
2082654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
2092654012fSReza Sabdar 
2102654012fSReza Sabdar 	switch (request->auth_data.auth_type) {
2112654012fSReza Sabdar 	case NDMP_AUTH_NONE:
2122654012fSReza Sabdar 		/*
2132654012fSReza Sabdar 		 * Allow no authorization for development.
2142654012fSReza Sabdar 		 * Comment the following for a non-secure production server.
2152654012fSReza Sabdar 		 */
2162654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Authorization denied.");
2172654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
2182654012fSReza Sabdar 		    "Authorization type should be md5 or cleartext.");
2192654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
2202654012fSReza Sabdar 		ndmpd_audit_connect(connection, EINVAL);
2212654012fSReza Sabdar 		break;
2222654012fSReza Sabdar 
2232654012fSReza Sabdar 	case NDMP_AUTH_TEXT:
2242654012fSReza Sabdar 		/* Check authorization.  */
2252654012fSReza Sabdar 		if ((uname = ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME)) == NULL ||
2262654012fSReza Sabdar 		    *uname == 0) {
2272654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Authorization denied.");
2282654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "User name is not set at server.");
2292654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
2302654012fSReza Sabdar 			ndmp_set_authorized(connection, FALSE);
2312654012fSReza Sabdar 			ndmp_send_reply(connection, (void *) &reply,
2322654012fSReza Sabdar 			    "sending ndmp_connect_client_auth reply");
2332654012fSReza Sabdar 			ndmpd_audit_connect(connection,
2342654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
2352654012fSReza Sabdar 			return;
2362654012fSReza Sabdar 		}
2372654012fSReza Sabdar 		auth = &request->auth_data.ndmp_auth_data_u.auth_text;
2382654012fSReza Sabdar 		if (strcmp(uname, auth->user) != 0) {
2392654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
2402654012fSReza Sabdar 			    "Authorization denied. Not a valid user.");
2412654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
2422654012fSReza Sabdar 			ndmpd_audit_connect(connection,
2432654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
2442654012fSReza Sabdar 			break;
2452654012fSReza Sabdar 		}
2462654012fSReza Sabdar 		passwd = ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD);
2472654012fSReza Sabdar 		if (!passwd || !*passwd) {
2482654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Authorization denied.");
2492654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
2502654012fSReza Sabdar 			    "Cleartext password is not set at server.");
2512654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
2522654012fSReza Sabdar 			ndmp_set_authorized(connection, FALSE);
2532654012fSReza Sabdar 			ndmp_send_reply(connection, (void *) &reply,
2542654012fSReza Sabdar 			    "sending ndmp_connect_client_auth reply");
2552654012fSReza Sabdar 			ndmpd_audit_connect(connection,
2562654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
2572654012fSReza Sabdar 			return;
2582654012fSReza Sabdar 		} else {
2592654012fSReza Sabdar 			dec_passwd = ndmp_base64_decode(passwd);
2602654012fSReza Sabdar 		}
2612654012fSReza Sabdar 		if (!dec_passwd || !*dec_passwd ||
2622654012fSReza Sabdar 		    strcmp(auth->password, dec_passwd) != 0) {
2632654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
2642654012fSReza Sabdar 			    "Authorization denied. Invalid password.");
2652654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
2662654012fSReza Sabdar 		} else {
2672654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Authorization granted.");
2682654012fSReza Sabdar 		}
2692654012fSReza Sabdar 		ndmpd_audit_connect(connection, reply.error ?
2702654012fSReza Sabdar 		    ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
2712654012fSReza Sabdar 
2722654012fSReza Sabdar 		free(dec_passwd);
2732654012fSReza Sabdar 		break;
2742654012fSReza Sabdar 
2752654012fSReza Sabdar 	case NDMP_AUTH_MD5:
2762654012fSReza Sabdar 		/* Check authorization.  */
2772654012fSReza Sabdar 		if ((uname = ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME)) == NULL ||
2782654012fSReza Sabdar 		    *uname == 0) {
2792654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Authorization denied.");
2802654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,  "User name is not set at server.");
2812654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
2822654012fSReza Sabdar 			ndmp_set_authorized(connection, FALSE);
2832654012fSReza Sabdar 			ndmp_send_reply(connection, (void *) &reply,
2842654012fSReza Sabdar 			    "sending ndmp_connect_client_auth reply");
2852654012fSReza Sabdar 			ndmpd_audit_connect(connection,
2862654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
2872654012fSReza Sabdar 			return;
2882654012fSReza Sabdar 		}
2892654012fSReza Sabdar 		md5 = &request->auth_data.ndmp_auth_data_u.auth_md5;
2902654012fSReza Sabdar 		passwd = ndmpd_get_prop(NDMP_CRAM_MD5_PASSWORD);
2912654012fSReza Sabdar 		if (!passwd || !*passwd) {
2922654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Authorization denied.");
2932654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "MD5 password is not set at server.");
2942654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
2952654012fSReza Sabdar 			ndmp_set_authorized(connection, FALSE);
2962654012fSReza Sabdar 			ndmp_send_reply(connection, (void *) &reply,
2972654012fSReza Sabdar 			    "sending ndmp_connect_client_auth reply");
2982654012fSReza Sabdar 			ndmpd_audit_connect(connection,
2992654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
3002654012fSReza Sabdar 			return;
3012654012fSReza Sabdar 		} else {
3022654012fSReza Sabdar 			dec_passwd = ndmp_base64_decode(passwd);
3032654012fSReza Sabdar 		}
3042654012fSReza Sabdar 		session = ndmp_get_client_data(connection);
3052654012fSReza Sabdar 		create_md5_digest(md5_digest, dec_passwd,
3062654012fSReza Sabdar 		    session->ns_challenge);
3072654012fSReza Sabdar 
3082654012fSReza Sabdar 		if (strcmp(uname, md5->user) != 0) {
3092654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
3102654012fSReza Sabdar 			    "Authorization denied. Not a valid user.");
3112654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
3122654012fSReza Sabdar 		} else if (memcmp(md5_digest, md5->auth_digest,
3132654012fSReza Sabdar 		    sizeof (md5_digest)) != 0) {
3142654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
3152654012fSReza Sabdar 			    "Authorization denied. Invalid password.");
3162654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
3172654012fSReza Sabdar 		} else {
3182654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Authorization granted");
3192654012fSReza Sabdar 		}
3202654012fSReza Sabdar 		ndmpd_audit_connect(connection, reply.error ?
3212654012fSReza Sabdar 		    ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
3222654012fSReza Sabdar 
3232654012fSReza Sabdar 		free(dec_passwd);
3242654012fSReza Sabdar 		break;
3252654012fSReza Sabdar 
3262654012fSReza Sabdar 	default:
3272654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
3282654012fSReza Sabdar 	}
3292654012fSReza Sabdar 
3302654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR)
3312654012fSReza Sabdar 		ndmp_set_authorized(connection, TRUE);
3322654012fSReza Sabdar 	else
3332654012fSReza Sabdar 		ndmp_set_authorized(connection, FALSE);
3342654012fSReza Sabdar 
3352654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
3362654012fSReza Sabdar 	    "sending ndmp_connect_client_auth reply");
3372654012fSReza Sabdar }
3382654012fSReza Sabdar 
3392654012fSReza Sabdar 
3402654012fSReza Sabdar /*
3412654012fSReza Sabdar  * ndmpd_connect_server_auth_v2
3422654012fSReza Sabdar  *
3432654012fSReza Sabdar  * This handler authenticates the server to the client.
3442654012fSReza Sabdar  *
3452654012fSReza Sabdar  * Parameters:
3462654012fSReza Sabdar  *   connection (input) - connection handle.
3472654012fSReza Sabdar  *   msginfo    (input) - request message.
3482654012fSReza Sabdar  *
3492654012fSReza Sabdar  * Returns:
3502654012fSReza Sabdar  *   void
3512654012fSReza Sabdar  */
3522654012fSReza Sabdar void
ndmpd_connect_server_auth_v2(ndmp_connection_t * connection,void * body)3532654012fSReza Sabdar ndmpd_connect_server_auth_v2(ndmp_connection_t *connection, void *body)
3542654012fSReza Sabdar {
3552654012fSReza Sabdar 	ndmp_connect_server_auth_request *request;
3562654012fSReza Sabdar 	ndmp_connect_server_auth_reply reply;
3572654012fSReza Sabdar 
3582654012fSReza Sabdar 	request = (ndmp_connect_server_auth_request *)body;
3592654012fSReza Sabdar 
3602654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "auth_type:%s",
3612654012fSReza Sabdar 	    request->client_attr.auth_type == NDMP_AUTH_NONE ? "None" :
3622654012fSReza Sabdar 	    (request->client_attr.auth_type == NDMP_AUTH_TEXT ? "Text" :
3632654012fSReza Sabdar 	    (request->client_attr.auth_type == NDMP_AUTH_MD5 ? "MD5" :
3642654012fSReza Sabdar 	    "Invalid")));
3652654012fSReza Sabdar 
3662654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
3672654012fSReza Sabdar 	reply.auth_result.auth_type = request->client_attr.auth_type;
3682654012fSReza Sabdar 	switch (request->client_attr.auth_type) {
3692654012fSReza Sabdar 	case NDMP_AUTH_NONE:
3702654012fSReza Sabdar 		break;
3712654012fSReza Sabdar 
3722654012fSReza Sabdar 	case NDMP_AUTH_TEXT:
3732654012fSReza Sabdar 		reply.auth_result.ndmp_auth_data_u.auth_text.user = "ndmpd";
3742654012fSReza Sabdar 		reply.auth_result.ndmp_auth_data_u.auth_text.password =
3752654012fSReza Sabdar 		    "ndmpsdk";
3762654012fSReza Sabdar 		break;
3772654012fSReza Sabdar 
3782654012fSReza Sabdar 	case NDMP_AUTH_MD5:
3792654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
3802654012fSReza Sabdar 		break;
3812654012fSReza Sabdar 
3822654012fSReza Sabdar 	default:
3832654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
3842654012fSReza Sabdar 	}
3852654012fSReza Sabdar 
3862654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
3872654012fSReza Sabdar 	    "sending ndmp_connect_auth reply");
3882654012fSReza Sabdar }
3892654012fSReza Sabdar 
3902654012fSReza Sabdar 
3912654012fSReza Sabdar /*
3922654012fSReza Sabdar  * ndmpd_connect_close_v2
3932654012fSReza Sabdar  *
3942654012fSReza Sabdar  * This handler closes the connection.
3952654012fSReza Sabdar  *
3962654012fSReza Sabdar  * Parameters:
3972654012fSReza Sabdar  *   connection (input) - connection handle.
3982654012fSReza Sabdar  *   msginfo    (input) - request message.
3992654012fSReza Sabdar  *
4002654012fSReza Sabdar  * Returns:
4012654012fSReza Sabdar  *   void
4022654012fSReza Sabdar  */
4032654012fSReza Sabdar /*ARGSUSED*/
4042654012fSReza Sabdar void
ndmpd_connect_close_v2(ndmp_connection_t * connection,void * body)4052654012fSReza Sabdar ndmpd_connect_close_v2(ndmp_connection_t *connection, void *body)
4062654012fSReza Sabdar {
4072654012fSReza Sabdar 	ndmpd_session_t *session;
4082654012fSReza Sabdar 
4092654012fSReza Sabdar 	if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) {
4102654012fSReza Sabdar 		(void) ndmp_close(connection);
4112654012fSReza Sabdar 		session->ns_eof = TRUE;
4122654012fSReza Sabdar 	}
4132654012fSReza Sabdar }
4142654012fSReza Sabdar 
4152654012fSReza Sabdar /*
4162654012fSReza Sabdar  * ************************************************************************
4172654012fSReza Sabdar  * NDMP V3 HANDLERS
4182654012fSReza Sabdar  * ************************************************************************
4192654012fSReza Sabdar  */
4202654012fSReza Sabdar 
4212654012fSReza Sabdar /*
4222654012fSReza Sabdar  * ndmpd_connect_client_auth_v3
4232654012fSReza Sabdar  *
4242654012fSReza Sabdar  * This handler authorizes the NDMP connection.
4252654012fSReza Sabdar  *
4262654012fSReza Sabdar  * Parameters:
4272654012fSReza Sabdar  *   connection (input) - connection handle.
4282654012fSReza Sabdar  *   msginfo    (input) - request message.
4292654012fSReza Sabdar  *
4302654012fSReza Sabdar  * Returns:
4312654012fSReza Sabdar  *   void
4322654012fSReza Sabdar  */
4332654012fSReza Sabdar void
ndmpd_connect_client_auth_v3(ndmp_connection_t * connection,void * body)4342654012fSReza Sabdar ndmpd_connect_client_auth_v3(ndmp_connection_t *connection, void *body)
4352654012fSReza Sabdar {
4362654012fSReza Sabdar 	ndmp_connect_client_auth_request_v3 *request;
4372654012fSReza Sabdar 	ndmp_connect_client_auth_reply_v3 reply;
4382654012fSReza Sabdar 	ndmp_auth_text_v3 *auth;
4392654012fSReza Sabdar 	ndmpd_session_t *session;
4402654012fSReza Sabdar 	ndmp_auth_md5_v3 *md5;
4412654012fSReza Sabdar 	struct in_addr addr;
4422654012fSReza Sabdar 	char *uname;
4432654012fSReza Sabdar 	char *type;
4442654012fSReza Sabdar 
4452654012fSReza Sabdar 	request = (ndmp_connect_client_auth_request_v3 *)body;
4462654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "auth_type %s",
4472654012fSReza Sabdar 	    request->auth_data.auth_type == NDMP_AUTH_NONE ? "None" :
4482654012fSReza Sabdar 	    request->auth_data.auth_type == NDMP_AUTH_TEXT ? "Text" :
4492654012fSReza Sabdar 	    request->auth_data.auth_type == NDMP_AUTH_MD5 ? "MD5" : "Invalid");
4502654012fSReza Sabdar 
4512654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
4522654012fSReza Sabdar 
4532654012fSReza Sabdar 	switch (request->auth_data.auth_type) {
4542654012fSReza Sabdar 	case NDMP_AUTH_NONE:
4552654012fSReza Sabdar 		type = "none";
4562654012fSReza Sabdar 		reply.error = NDMP_NOT_SUPPORTED_ERR;
4572654012fSReza Sabdar 		ndmpd_audit_connect(connection, ENOTSUP);
4582654012fSReza Sabdar 		break;
4592654012fSReza Sabdar 
4602654012fSReza Sabdar 	case NDMP_AUTH_TEXT:
4612654012fSReza Sabdar 		/* Check authorization.  */
4622654012fSReza Sabdar 		if ((uname = ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME)) == NULL ||
4632654012fSReza Sabdar 		    *uname == 0) {
4642654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Authorization denied.");
4652654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "User name is not set at server.");
4662654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
4672654012fSReza Sabdar 			ndmp_set_authorized(connection, FALSE);
4682654012fSReza Sabdar 			ndmp_send_reply(connection, (void *) &reply,
4692654012fSReza Sabdar 			    "sending ndmp_connect_client_auth reply");
4702654012fSReza Sabdar 			ndmpd_audit_connect(connection,
4712654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
4722654012fSReza Sabdar 			return;
4732654012fSReza Sabdar 		}
4742654012fSReza Sabdar 		type = "text";
4752654012fSReza Sabdar 		auth = &request->auth_data.ndmp_auth_data_v3_u.auth_text;
4762654012fSReza Sabdar 		reply.error = ndmpd_connect_auth_text(uname, auth->auth_id,
4772654012fSReza Sabdar 		    auth->auth_password);
4782654012fSReza Sabdar 		ndmpd_audit_connect(connection, reply.error ?
4792654012fSReza Sabdar 		    ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
4802654012fSReza Sabdar 		break;
4812654012fSReza Sabdar 
4822654012fSReza Sabdar 	case NDMP_AUTH_MD5:
4832654012fSReza Sabdar 		/* Check authorization.  */
4842654012fSReza Sabdar 		if ((uname = ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME)) == NULL ||
4852654012fSReza Sabdar 		    *uname == 0) {
4862654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Authorization denied.");
4872654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "User name is not set at server.");
4882654012fSReza Sabdar 			reply.error = NDMP_NOT_AUTHORIZED_ERR;
4892654012fSReza Sabdar 			ndmp_set_authorized(connection, FALSE);
4902654012fSReza Sabdar 			ndmp_send_reply(connection, (void *) &reply,
4912654012fSReza Sabdar 			    "sending ndmp_connect_client_auth reply");
4922654012fSReza Sabdar 			ndmpd_audit_connect(connection,
4932654012fSReza Sabdar 			    ADT_FAIL_PAM + PAM_AUTH_ERR);
4942654012fSReza Sabdar 			return;
4952654012fSReza Sabdar 		}
4962654012fSReza Sabdar 		type = "md5";
4972654012fSReza Sabdar 		session = ndmp_get_client_data(connection);
4982654012fSReza Sabdar 		md5 = &request->auth_data.ndmp_auth_data_v3_u.auth_md5;
4992654012fSReza Sabdar 		reply.error = ndmpd_connect_auth_md5(uname, md5->auth_id,
5002654012fSReza Sabdar 		    md5->auth_digest, session->ns_challenge);
5012654012fSReza Sabdar 		ndmpd_audit_connect(connection, reply.error ?
5022654012fSReza Sabdar 		    ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
5032654012fSReza Sabdar 		break;
5042654012fSReza Sabdar 
5052654012fSReza Sabdar 	default:
5062654012fSReza Sabdar 		type = "unknown";
5072654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
5082654012fSReza Sabdar 		ndmpd_audit_connect(connection, EINVAL);
5092654012fSReza Sabdar 	}
5102654012fSReza Sabdar 
5112654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR) {
5122654012fSReza Sabdar 		ndmp_set_authorized(connection, TRUE);
5132654012fSReza Sabdar 	} else {
5142654012fSReza Sabdar 		ndmp_set_authorized(connection, FALSE);
5152654012fSReza Sabdar 		if (tcp_get_peer(connection->conn_sock, &addr.s_addr,
5162654012fSReza Sabdar 		    NULL) != -1) {
5172654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
5182654012fSReza Sabdar 			    "Authorization(%s) denied for %s.", type,
5192654012fSReza Sabdar 			    inet_ntoa(IN_ADDR(addr)));
5202654012fSReza Sabdar 		}
5212654012fSReza Sabdar 	}
5222654012fSReza Sabdar 
5232654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
5242654012fSReza Sabdar 	    "sending ndmp_connect_auth reply");
5252654012fSReza Sabdar }
5262654012fSReza Sabdar 
5272654012fSReza Sabdar 
5282654012fSReza Sabdar /*
5292654012fSReza Sabdar  * ndmpd_connect_close_v3
5302654012fSReza Sabdar  *
5312654012fSReza Sabdar  * Close the connection to the DMA.
5322654012fSReza Sabdar  * Send the SHUTDOWN message before closing the socket connection to the DMA.
5332654012fSReza Sabdar  *
5342654012fSReza Sabdar  * Parameters:
5352654012fSReza Sabdar  *   connection (input) - connection handle.
5362654012fSReza Sabdar  *   msginfo    (input) - request message.
5372654012fSReza Sabdar  *
5382654012fSReza Sabdar  * Returns:
5392654012fSReza Sabdar  *   void
5402654012fSReza Sabdar  */
5412654012fSReza Sabdar /*ARGSUSED*/
5422654012fSReza Sabdar void
ndmpd_connect_close_v3(ndmp_connection_t * connection,void * body)5432654012fSReza Sabdar ndmpd_connect_close_v3(ndmp_connection_t *connection, void *body)
5442654012fSReza Sabdar {
5452654012fSReza Sabdar 	ndmpd_session_t *session;
546*a23888a3SJan Kryl 	ndmp_lbr_params_t *nlp;
5472654012fSReza Sabdar 	ndmp_notify_connected_request req;
5482654012fSReza Sabdar 
5492654012fSReza Sabdar 	if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection)))
5502654012fSReza Sabdar 		return;
551*a23888a3SJan Kryl 	if ((nlp = ndmp_get_nlp(session)) == NULL)
552*a23888a3SJan Kryl 		return;
5532654012fSReza Sabdar 
5542654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "ver: %u",
5552654012fSReza Sabdar 	    session->ns_protocol_version);
5562654012fSReza Sabdar 
5572654012fSReza Sabdar 	/* Send the SHUTDOWN message before closing the connection. */
5582654012fSReza Sabdar 	req.reason = NDMP_SHUTDOWN;
5592654012fSReza Sabdar 	req.protocol_version = session->ns_protocol_version;
5602654012fSReza Sabdar 	req.text_reason = "Connection closed by server.";
5612654012fSReza Sabdar 
5622654012fSReza Sabdar 	if (ndmp_send_request(connection, NDMP_NOTIFY_CONNECTION_STATUS,
5632654012fSReza Sabdar 	    NDMP_NO_ERR, (void *) &req, 0) < 0) {
5642654012fSReza Sabdar 		NDMP_LOG(LOG_NOTICE, "Sending connection shutdown notify");
5652654012fSReza Sabdar 		return;
5662654012fSReza Sabdar 	}
5672654012fSReza Sabdar 
568*a23888a3SJan Kryl 	(void) mutex_lock(&nlp->nlp_mtx);
5692654012fSReza Sabdar 	ndmp_close(connection);
5702654012fSReza Sabdar 	session->ns_eof = TRUE;
571*a23888a3SJan Kryl 	(void) cond_broadcast(&nlp->nlp_cv);
572*a23888a3SJan Kryl 	(void) mutex_unlock(&nlp->nlp_mtx);
5732654012fSReza Sabdar }
5742654012fSReza Sabdar 
5752654012fSReza Sabdar /*
5762654012fSReza Sabdar  * ************************************************************************
5772654012fSReza Sabdar  * NDMP V4 HANDLERS
5782654012fSReza Sabdar  * ************************************************************************
5792654012fSReza Sabdar  */
5802654012fSReza Sabdar 
5812654012fSReza Sabdar /*
5822654012fSReza Sabdar  * ************************************************************************
5832654012fSReza Sabdar  * LOCALS
5842654012fSReza Sabdar  * ************************************************************************
5852654012fSReza Sabdar  */
5862654012fSReza Sabdar 
5872654012fSReza Sabdar /*
5882654012fSReza Sabdar  * create_md5_digest
5892654012fSReza Sabdar  *
5902654012fSReza Sabdar  * This function uses the MD5 message-digest algorithm described
5912654012fSReza Sabdar  * in RFC1321 to authenticate the client using a shared secret (password).
5922654012fSReza Sabdar  * The message used to compute the MD5 digest is a concatenation of password,
5932654012fSReza Sabdar  * null padding, the 64 byte fixed length challenge and a repeat of the
5942654012fSReza Sabdar  * password. The length of the null padding is chosen to result in a 128 byte
5952654012fSReza Sabdar  * fixed length message. The lengh of the padding can be computed as
5962654012fSReza Sabdar  * 64 - 2*(length of the password). The client digest is computed using the
5972654012fSReza Sabdar  * server challenge from the NDMP_CONFIG_GET_AUTH_ATTR reply.
5982654012fSReza Sabdar  *
5992654012fSReza Sabdar  * Parameters:
6002654012fSReza Sabdar  *   digest (output) - 16 bytes MD5 digest
6012654012fSReza Sabdar  *   passwd (input) - user password
6022654012fSReza Sabdar  *   challenge (input) - 64 bytes server challenge
6032654012fSReza Sabdar  *
6042654012fSReza Sabdar  * Returns:
6052654012fSReza Sabdar  *   void
6062654012fSReza Sabdar  */
6072654012fSReza Sabdar static void
create_md5_digest(unsigned char * digest,char * passwd,unsigned char * challenge)6082654012fSReza Sabdar create_md5_digest(unsigned char *digest, char *passwd, unsigned char *challenge)
6092654012fSReza Sabdar {
6102654012fSReza Sabdar 	char buf[130];
6112654012fSReza Sabdar 	char *p = &buf[0];
6122654012fSReza Sabdar 	int len, i;
6132654012fSReza Sabdar 	MD5_CTX md;
6142654012fSReza Sabdar 	char *pwd;
6152654012fSReza Sabdar 
6162654012fSReza Sabdar 	*p = 0;
6172654012fSReza Sabdar 	pwd = passwd;
6182654012fSReza Sabdar 	if ((len = strlen(pwd)) > MD5_PASS_LIMIT)
6192654012fSReza Sabdar 		len = MD5_PASS_LIMIT;
6202654012fSReza Sabdar 	(void) memcpy(p, pwd, len);
6212654012fSReza Sabdar 	p += len;
6222654012fSReza Sabdar 
6232654012fSReza Sabdar 	for (i = 0; i < MD5_CHALLENGE_SIZE - 2 * len; i++)
6242654012fSReza Sabdar 		*p++ = 0;
6252654012fSReza Sabdar 
6262654012fSReza Sabdar 	(void) memcpy(p, challenge, MD5_CHALLENGE_SIZE);
6272654012fSReza Sabdar 	p += MD5_CHALLENGE_SIZE;
6282654012fSReza Sabdar 	(void) strlcpy(p, pwd, MD5_PASS_LIMIT);
6292654012fSReza Sabdar 
6302654012fSReza Sabdar 	MD5Init(&md);
6312654012fSReza Sabdar 	MD5Update(&md, buf, 128);
6322654012fSReza Sabdar 	MD5Final(digest, &md);
6332654012fSReza Sabdar }
6342654012fSReza Sabdar 
6352654012fSReza Sabdar /*
6362654012fSReza Sabdar  * ndmp_connect_list_find
6372654012fSReza Sabdar  *
6382654012fSReza Sabdar  * Find the element in the active connection list.
6392654012fSReza Sabdar  *
6402654012fSReza Sabdar  * Parameters:
6412654012fSReza Sabdar  *   connection (input) - connection handler.
6422654012fSReza Sabdar  *
6432654012fSReza Sabdar  * Returns:
6442654012fSReza Sabdar  *   NULL - error
6452654012fSReza Sabdar  *   connection list element pointer
6462654012fSReza Sabdar  */
6472654012fSReza Sabdar static struct conn_list *
ndmp_connect_list_find(ndmp_connection_t * connection)6482654012fSReza Sabdar ndmp_connect_list_find(ndmp_connection_t *connection)
6492654012fSReza Sabdar {
6502654012fSReza Sabdar 	struct conn_list *clp;
6512654012fSReza Sabdar 
6522654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "connection: 0x%p",
6532654012fSReza Sabdar 	    connection);
6542654012fSReza Sabdar 
6552654012fSReza Sabdar 	LIST_FOREACH(clp, &cl_head, cl_q) {
6562654012fSReza Sabdar 		if (clp->cl_conn == connection) {
6572654012fSReza Sabdar 			(void) mutex_unlock(&cl_mutex);
6582654012fSReza Sabdar 			return (clp);
6592654012fSReza Sabdar 		}
6602654012fSReza Sabdar 	}
6612654012fSReza Sabdar 	return (NULL);
6622654012fSReza Sabdar }
6632654012fSReza Sabdar 
6642654012fSReza Sabdar /*
6652654012fSReza Sabdar  * ndmpconnect_list_add
6662654012fSReza Sabdar  *
6672654012fSReza Sabdar  * Add the new connection to the list of the active connections.
6682654012fSReza Sabdar  *
6692654012fSReza Sabdar  * Parameters:
6702654012fSReza Sabdar  *   connection (input) - connection handler.
6712654012fSReza Sabdar  *   id (input/output) - pointer to connection id.
6722654012fSReza Sabdar  *
6732654012fSReza Sabdar  * Returns:
6742654012fSReza Sabdar  *   0 - success
6752654012fSReza Sabdar  *  -1 - error
6762654012fSReza Sabdar  */
6772654012fSReza Sabdar int
ndmp_connect_list_add(ndmp_connection_t * connection,int * id)6782654012fSReza Sabdar ndmp_connect_list_add(ndmp_connection_t *connection, int *id)
6792654012fSReza Sabdar {
6802654012fSReza Sabdar 	struct conn_list *clp;
6812654012fSReza Sabdar 
6822654012fSReza Sabdar 	if (connection == NULL) {
6832654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
6842654012fSReza Sabdar 		return (-1);
6852654012fSReza Sabdar 	}
6862654012fSReza Sabdar 
6872654012fSReza Sabdar 	if ((clp = ndmp_malloc(sizeof (struct conn_list))) == NULL)
6882654012fSReza Sabdar 		return (-1);
6892654012fSReza Sabdar 
6902654012fSReza Sabdar 	clp->cl_conn = connection;
6912654012fSReza Sabdar 	clp->cl_id = *id;
6922654012fSReza Sabdar 
6932654012fSReza Sabdar 	(void) mutex_lock(&cl_mutex);
6942654012fSReza Sabdar 	LIST_INSERT_HEAD(&cl_head, clp, cl_q);
6952654012fSReza Sabdar 	(*id)++;
6962654012fSReza Sabdar 	(void) mutex_unlock(&cl_mutex);
6972654012fSReza Sabdar 
6982654012fSReza Sabdar 	return (0);
6992654012fSReza Sabdar }
7002654012fSReza Sabdar 
7012654012fSReza Sabdar /*
7022654012fSReza Sabdar  * ndmp_connect_list_del
7032654012fSReza Sabdar  *
7042654012fSReza Sabdar  * Delete the specified connection from the list.
7052654012fSReza Sabdar  *
7062654012fSReza Sabdar  * Parameters:
7072654012fSReza Sabdar  *   connection (input) - connection handler.
7082654012fSReza Sabdar  *
7092654012fSReza Sabdar  * Returns:
7102654012fSReza Sabdar  *   0 - success
7112654012fSReza Sabdar  *  -1 - error
7122654012fSReza Sabdar  */
7132654012fSReza Sabdar int
ndmp_connect_list_del(ndmp_connection_t * connection)7142654012fSReza Sabdar ndmp_connect_list_del(ndmp_connection_t *connection)
7152654012fSReza Sabdar {
7162654012fSReza Sabdar 	struct conn_list *clp;
7172654012fSReza Sabdar 
7182654012fSReza Sabdar 	(void) mutex_lock(&cl_mutex);
7192654012fSReza Sabdar 	if (!(clp = ndmp_connect_list_find(connection))) {
7202654012fSReza Sabdar 		(void) mutex_unlock(&cl_mutex);
7212654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "connection not found");
7222654012fSReza Sabdar 		return (-1);
7232654012fSReza Sabdar 	}
7242654012fSReza Sabdar 
7252654012fSReza Sabdar 	LIST_REMOVE(clp, cl_q);
7262654012fSReza Sabdar 	(void) mutex_unlock(&cl_mutex);
7272654012fSReza Sabdar 	free(clp);
7282654012fSReza Sabdar 
7292654012fSReza Sabdar 	return (0);
7302654012fSReza Sabdar }
7312654012fSReza Sabdar 
7322654012fSReza Sabdar 
7332654012fSReza Sabdar /*
7342654012fSReza Sabdar  * ndmpconnect_list_find_id
7352654012fSReza Sabdar  *
7362654012fSReza Sabdar  * Find the element specified by its id in the list of active connections.
7372654012fSReza Sabdar  *
7382654012fSReza Sabdar  * Parameters:
7392654012fSReza Sabdar  *   id (input) - connection id.
7402654012fSReza Sabdar  *
7412654012fSReza Sabdar  * Returns:
7422654012fSReza Sabdar  *   NULL - error
7432654012fSReza Sabdar  *   connection list element pointer
7442654012fSReza Sabdar  */
7452654012fSReza Sabdar static struct conn_list *
ndmp_connect_list_find_id(int id)7462654012fSReza Sabdar ndmp_connect_list_find_id(int id)
7472654012fSReza Sabdar {
7482654012fSReza Sabdar 	struct conn_list *clp;
7492654012fSReza Sabdar 
7502654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "id: %d", id);
7512654012fSReza Sabdar 
7522654012fSReza Sabdar 	(void) mutex_lock(&cl_mutex);
7532654012fSReza Sabdar 	LIST_FOREACH(clp, &cl_head, cl_q) {
7542654012fSReza Sabdar 		if (clp->cl_id == id) {
7552654012fSReza Sabdar 			(void) mutex_unlock(&cl_mutex);
7562654012fSReza Sabdar 			return (clp);
7572654012fSReza Sabdar 		}
7582654012fSReza Sabdar 	}
7592654012fSReza Sabdar 
7602654012fSReza Sabdar 	(void) mutex_unlock(&cl_mutex);
7612654012fSReza Sabdar 	return (NULL);
7622654012fSReza Sabdar }
7632654012fSReza Sabdar 
7642654012fSReza Sabdar /*
7652654012fSReza Sabdar  * Get common fields of the active connection.
7662654012fSReza Sabdar  */
7672654012fSReza Sabdar static void
ndmp_connect_get_conn(struct conn_list * clp,ndmp_door_ctx_t * enc_ctx)7682654012fSReza Sabdar ndmp_connect_get_conn(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx)
7692654012fSReza Sabdar {
7702654012fSReza Sabdar 	int port;
7712654012fSReza Sabdar 	struct in_addr addr;
7722654012fSReza Sabdar 	char cl_addr[NDMP_CL_ADDR_LEN];
7732654012fSReza Sabdar 	ndmpd_session_t *session;
7742654012fSReza Sabdar 
7752654012fSReza Sabdar 	if (!(session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn)))
7762654012fSReza Sabdar 		return;
7772654012fSReza Sabdar 
7782654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, clp->cl_id);
7792654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_protocol_version);
7802654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, clp->cl_conn->conn_authorized);
7812654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_eof);
7822654012fSReza Sabdar 	if (tcp_get_peer(clp->cl_conn->conn_sock, &(addr.s_addr), &port) != -1)
7832654012fSReza Sabdar 		(void) snprintf(cl_addr, NDMP_CL_ADDR_LEN, "%s:%d",
7842654012fSReza Sabdar 		    (char *)inet_ntoa(addr), port);
7852654012fSReza Sabdar 	else
7862654012fSReza Sabdar 		cl_addr[0] = '\0';
7872654012fSReza Sabdar 	ndmp_door_put_string(enc_ctx, cl_addr);
7882654012fSReza Sabdar }
7892654012fSReza Sabdar 
7902654012fSReza Sabdar /*
7912654012fSReza Sabdar  * Get the connection SCSI info.
7922654012fSReza Sabdar  */
7932654012fSReza Sabdar static void
ndmp_connect_get_scsi_v2(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)7942654012fSReza Sabdar ndmp_connect_get_scsi_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
7952654012fSReza Sabdar {
7962654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_is_open);
7972654012fSReza Sabdar 	ndmp_door_put_string(enc_ctx, session->ns_scsi.sd_adapter_name);
7982654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_valid_target_set);
7992654012fSReza Sabdar 	if (session->ns_scsi.sd_valid_target_set) {
8002654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_sid);
8012654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, session->ns_scsi.sd_lun);
8022654012fSReza Sabdar 	}
8032654012fSReza Sabdar }
8042654012fSReza Sabdar 
8052654012fSReza Sabdar /*
8062654012fSReza Sabdar  * Get the connection tape info.
8072654012fSReza Sabdar  */
8082654012fSReza Sabdar static void
ndmp_connect_get_tape_v2(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)8092654012fSReza Sabdar ndmp_connect_get_tape_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
8102654012fSReza Sabdar {
8112654012fSReza Sabdar 	char dev_name[NDMP_TAPE_DEV_NAME];
8122654012fSReza Sabdar 
8132654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_tape.td_fd);
8142654012fSReza Sabdar 	if (session->ns_tape.td_fd != -1) {
8152654012fSReza Sabdar 		ndmp_door_put_uint64(enc_ctx, session->ns_tape.td_record_count);
8162654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, session->ns_tape.td_mode);
8172654012fSReza Sabdar 		(void) snprintf(dev_name, NDMP_TAPE_DEV_NAME, "%st%02x%x",
8182654012fSReza Sabdar 		    session->ns_tape.td_adapter_name, session->ns_tape.td_sid,
8192654012fSReza Sabdar 		    session->ns_tape.td_lun);
8202654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, dev_name);
8212654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, session->ns_tape.td_adapter_name);
8222654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, session->ns_tape.td_sid);
8232654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, session->ns_tape.td_lun);
8242654012fSReza Sabdar 	}
8252654012fSReza Sabdar }
8262654012fSReza Sabdar 
8272654012fSReza Sabdar /*
8282654012fSReza Sabdar  * Get the connection mover info.
8292654012fSReza Sabdar  */
8302654012fSReza Sabdar static void
ndmp_connect_get_mover_v2(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)8312654012fSReza Sabdar ndmp_connect_get_mover_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
8322654012fSReza Sabdar {
8332654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_state);
8342654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_mode);
8352654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_pause_reason);
8362654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_halt_reason);
8372654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_record_size);
8382654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_record_num);
8392654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_position);
8402654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_window_offset);
8412654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_mover.md_window_length);
8422654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_sock);
8432654012fSReza Sabdar }
8442654012fSReza Sabdar 
8452654012fSReza Sabdar /*
8462654012fSReza Sabdar  * Get the connection common data info.
8472654012fSReza Sabdar  */
8482654012fSReza Sabdar static void
ndmp_connect_get_data_common(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)8492654012fSReza Sabdar ndmp_connect_get_data_common(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
8502654012fSReza Sabdar {
8512654012fSReza Sabdar 	int i;
8522654012fSReza Sabdar 	ndmp_pval *ep;
8532654012fSReza Sabdar 	int len;
8542654012fSReza Sabdar 
8552654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_operation);
8562654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_state);
8572654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_halt_reason);
8582654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_sock);
8592654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_mover.addr_type);
8602654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_abort);
8612654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_read_offset);
8622654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_read_length);
8632654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_data_size);
8642654012fSReza Sabdar 	/* verify data.env has as much data as in session->ns_data.dd_env_len */
8652654012fSReza Sabdar 	len = 0;
8662654012fSReza Sabdar 	ep = session->ns_data.dd_env;
8672654012fSReza Sabdar 	for (i = 0; ep && i < session->ns_data.dd_env_len; i++, ep++)
8682654012fSReza Sabdar 		len++;
8692654012fSReza Sabdar 
8702654012fSReza Sabdar 	/* put the len */
8712654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
8722654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, len);
8732654012fSReza Sabdar 	ep = session->ns_data.dd_env;
8742654012fSReza Sabdar 	for (i = 0; i < len; i++, ep++) {
8752654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, ep->name);
8762654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, ep->value);
8772654012fSReza Sabdar 	}
8782654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
8792654012fSReza Sabdar }
8802654012fSReza Sabdar 
8812654012fSReza Sabdar /*
8822654012fSReza Sabdar  * Get the connection data info.
8832654012fSReza Sabdar  */
8842654012fSReza Sabdar static void
ndmp_connect_get_data_v2(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)8852654012fSReza Sabdar ndmp_connect_get_data_v2(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
8862654012fSReza Sabdar {
8872654012fSReza Sabdar 	int i;
8882654012fSReza Sabdar 	ndmp_name *np;
8892654012fSReza Sabdar 	char tcp_addr[NDMP_TCP_ADDR_SIZE];
8902654012fSReza Sabdar 
8912654012fSReza Sabdar 	ndmp_connect_get_data_common(session, enc_ctx);
8922654012fSReza Sabdar 
8932654012fSReza Sabdar 	switch (session->ns_data.dd_mover.addr_type) {
8942654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
8952654012fSReza Sabdar 		(void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s", "Local");
8962654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, tcp_addr);
8972654012fSReza Sabdar 		break;
8982654012fSReza Sabdar 	case NDMP_ADDR_TCP:
8992654012fSReza Sabdar 		(void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d",
9002654012fSReza Sabdar 		    (char *)inet_ntoa(IN_ADDR(
9012654012fSReza Sabdar 		    session->ns_data.dd_mover.ndmp_mover_addr_u.addr.ip_addr)),
9022654012fSReza Sabdar 		    session->ns_data.dd_mover.ndmp_mover_addr_u.addr.port);
9032654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, tcp_addr);
9042654012fSReza Sabdar 		break;
9052654012fSReza Sabdar 	default:
9062654012fSReza Sabdar 		(void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s", "Unknown");
9072654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, tcp_addr);
9082654012fSReza Sabdar 	}
9092654012fSReza Sabdar 
9102654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_nlist_len);
9112654012fSReza Sabdar 	np = session->ns_data.dd_nlist;
9122654012fSReza Sabdar 	for (i = 0; np && i < (int)session->ns_data.dd_nlist_len; i++, np++) {
9132654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, np->name);
9142654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, np->dest);
9152654012fSReza Sabdar 	}
9162654012fSReza Sabdar }
9172654012fSReza Sabdar 
9182654012fSReza Sabdar /*
9192654012fSReza Sabdar  * Get V2 connection info.
9202654012fSReza Sabdar  */
9212654012fSReza Sabdar static void
ndmp_connect_get_v2(ndmp_connection_t * connection,ndmp_door_ctx_t * enc_ctx)9222654012fSReza Sabdar ndmp_connect_get_v2(ndmp_connection_t *connection, ndmp_door_ctx_t *enc_ctx)
9232654012fSReza Sabdar {
9242654012fSReza Sabdar 	ndmpd_session_t *session;
9252654012fSReza Sabdar 
9262654012fSReza Sabdar 	if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) {
9272654012fSReza Sabdar 		ndmp_connect_get_scsi_v2(session, enc_ctx);
9282654012fSReza Sabdar 		ndmp_connect_get_tape_v2(session, enc_ctx);
9292654012fSReza Sabdar 		ndmp_connect_get_mover_v2(session, enc_ctx);
9302654012fSReza Sabdar 		ndmp_connect_get_data_v2(session, enc_ctx);
9312654012fSReza Sabdar 	}
9322654012fSReza Sabdar }
9332654012fSReza Sabdar 
9342654012fSReza Sabdar /*
9352654012fSReza Sabdar  * Get the V3 connection mover info.
9362654012fSReza Sabdar  */
9372654012fSReza Sabdar static void
ndmp_connect_get_mover_v3(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)9382654012fSReza Sabdar ndmp_connect_get_mover_v3(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
9392654012fSReza Sabdar {
9402654012fSReza Sabdar 	char tcp_addr[NDMP_TCP_ADDR_SIZE];
9412654012fSReza Sabdar 
9422654012fSReza Sabdar 	/* get all the V2 mover data first */
9432654012fSReza Sabdar 	ndmp_connect_get_mover_v2(session, enc_ctx);
9442654012fSReza Sabdar 
9452654012fSReza Sabdar 	/* get the V3 mover data now */
9462654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_listen_sock);
9472654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_mover.md_data_addr.addr_type);
9482654012fSReza Sabdar 	tcp_addr[0] = '\0';
9492654012fSReza Sabdar 	(void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d",
9502654012fSReza Sabdar 	    (char *)
9512654012fSReza Sabdar 	    inet_ntoa(IN_ADDR(session->ns_mover.md_data_addr.tcp_ip_v3)),
9522654012fSReza Sabdar 	    (int)session->ns_mover.md_data_addr.tcp_port_v3);
9532654012fSReza Sabdar 	ndmp_door_put_string(enc_ctx, tcp_addr);
9542654012fSReza Sabdar }
9552654012fSReza Sabdar 
9562654012fSReza Sabdar /*
9572654012fSReza Sabdar  * Get the connection data info.
9582654012fSReza Sabdar  */
9592654012fSReza Sabdar static void
ndmp_connect_get_data_v3(ndmpd_session_t * session,ndmp_door_ctx_t * enc_ctx)9602654012fSReza Sabdar ndmp_connect_get_data_v3(ndmpd_session_t *session, ndmp_door_ctx_t *enc_ctx)
9612654012fSReza Sabdar {
9622654012fSReza Sabdar 	ulong_t i;
9632654012fSReza Sabdar 	mem_ndmp_name_v3_t *np;
9642654012fSReza Sabdar 	char tcp_addr[NDMP_TCP_ADDR_SIZE];
9652654012fSReza Sabdar 
9662654012fSReza Sabdar 	ndmp_connect_get_data_common(session, enc_ctx);
9672654012fSReza Sabdar 
9682654012fSReza Sabdar 	(void) snprintf(tcp_addr, NDMP_TCP_ADDR_SIZE, "%s:%d",
9692654012fSReza Sabdar 	    (char *)inet_ntoa(IN_ADDR(session->ns_data.dd_data_addr.tcp_ip_v3)),
9702654012fSReza Sabdar 	    (int)session->ns_data.dd_data_addr.tcp_port_v3);
9712654012fSReza Sabdar 	ndmp_door_put_string(enc_ctx, tcp_addr);
9722654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, session->ns_data.dd_listen_sock);
9732654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx,
9742654012fSReza Sabdar 	    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
9752654012fSReza Sabdar 	ndmp_door_put_uint64(enc_ctx, session->ns_data.dd_nlist_len);
9762654012fSReza Sabdar 	np = session->ns_data.dd_nlist_v3;
9772654012fSReza Sabdar 	for (i = 0; np && i < (int)session->ns_data.dd_nlist_len; i++, np++) {
9782654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, np->nm3_opath);
9792654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, np->nm3_dpath);
9802654012fSReza Sabdar 		ndmp_door_put_uint64(enc_ctx, np->nm3_node);
9812654012fSReza Sabdar 		ndmp_door_put_uint64(enc_ctx, np->nm3_fh_info);
9822654012fSReza Sabdar 	}
9832654012fSReza Sabdar }
9842654012fSReza Sabdar 
9852654012fSReza Sabdar /*
9862654012fSReza Sabdar  * Get V3 connection info.
9872654012fSReza Sabdar  */
9882654012fSReza Sabdar static void
ndmp_connect_get_v3(ndmp_connection_t * connection,ndmp_door_ctx_t * enc_ctx)9892654012fSReza Sabdar ndmp_connect_get_v3(ndmp_connection_t *connection, ndmp_door_ctx_t *enc_ctx)
9902654012fSReza Sabdar {
9912654012fSReza Sabdar 	ndmpd_session_t *session;
9922654012fSReza Sabdar 
9932654012fSReza Sabdar 	if ((session = (ndmpd_session_t *)ndmp_get_client_data(connection))) {
9942654012fSReza Sabdar 		ndmp_connect_get_scsi_v2(session, enc_ctx);
9952654012fSReza Sabdar 		ndmp_connect_get_tape_v2(session, enc_ctx);
9962654012fSReza Sabdar 		ndmp_connect_get_mover_v3(session, enc_ctx);
9972654012fSReza Sabdar 		ndmp_connect_get_data_v3(session, enc_ctx);
9982654012fSReza Sabdar 	}
9992654012fSReza Sabdar }
10002654012fSReza Sabdar 
10012654012fSReza Sabdar /*
10022654012fSReza Sabdar  * Get the list of all active sessions to the clients.  For each version,
10032654012fSReza Sabdar  * call the appropriate get function.
10042654012fSReza Sabdar  */
10052654012fSReza Sabdar static void
connection_get(struct conn_list * clp,ndmp_door_ctx_t * enc_ctx)10062654012fSReza Sabdar connection_get(struct conn_list *clp, ndmp_door_ctx_t *enc_ctx)
10072654012fSReza Sabdar {
10082654012fSReza Sabdar 	ndmpd_session_t *session;
10092654012fSReza Sabdar 
10102654012fSReza Sabdar 	session = (ndmpd_session_t *)ndmp_get_client_data(clp->cl_conn);
10112654012fSReza Sabdar 	if (!session) {
10122654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, NDMP_SESSION_NODATA);
10132654012fSReza Sabdar 		return;
10142654012fSReza Sabdar 	}
10152654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, NDMP_SESSION_DATA);
10162654012fSReza Sabdar 
10172654012fSReza Sabdar 	switch (session->ns_protocol_version) {
10182654012fSReza Sabdar 	case NDMPV2:
10192654012fSReza Sabdar 		ndmp_connect_get_conn(clp, enc_ctx);
10202654012fSReza Sabdar 		ndmp_connect_get_v2(clp->cl_conn, enc_ctx);
10212654012fSReza Sabdar 		break;
10222654012fSReza Sabdar 	case NDMPV3:
10232654012fSReza Sabdar 	case NDMPV4:
10242654012fSReza Sabdar 		ndmp_connect_get_conn(clp, enc_ctx);
10252654012fSReza Sabdar 		ndmp_connect_get_v3(clp->cl_conn, enc_ctx);
10262654012fSReza Sabdar 		break;
10272654012fSReza Sabdar 	default:
10282654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
10292654012fSReza Sabdar 		    "Invalid session (0x%p) version 0x%x", session,
10302654012fSReza Sabdar 		    session->ns_protocol_version);
10312654012fSReza Sabdar 	}
10322654012fSReza Sabdar }
10332654012fSReza Sabdar 
10342654012fSReza Sabdar /*
10352654012fSReza Sabdar  * ndmpd_connect_kill
10362654012fSReza Sabdar  *
10372654012fSReza Sabdar  * Kill the connection based on its version.
10382654012fSReza Sabdar  *
10392654012fSReza Sabdar  * Parameters:
10402654012fSReza Sabdar  *   connection (input) - connection handler.
10412654012fSReza Sabdar  *
10422654012fSReza Sabdar  * Returns:
10432654012fSReza Sabdar  *   0 - success
10442654012fSReza Sabdar  *  -1 - error
10452654012fSReza Sabdar  */
10462654012fSReza Sabdar int
ndmpd_connect_kill(ndmp_connection_t * connection)10472654012fSReza Sabdar ndmpd_connect_kill(ndmp_connection_t *connection)
10482654012fSReza Sabdar {
10492654012fSReza Sabdar 	ndmpd_session_t *session;
10502654012fSReza Sabdar 
10512654012fSReza Sabdar 	if (!(session = (ndmpd_session_t *)ndmp_get_client_data(connection)))
10522654012fSReza Sabdar 		return (-1);
10532654012fSReza Sabdar 
10542654012fSReza Sabdar 	switch (session->ns_protocol_version) {
10552654012fSReza Sabdar 	case NDMPV2:
10562654012fSReza Sabdar 		ndmpd_connect_close_v2(connection, (void *)NULL);
10572654012fSReza Sabdar 		break;
10582654012fSReza Sabdar 	case NDMPV3:
10592654012fSReza Sabdar 	case NDMPV4:
10602654012fSReza Sabdar 		ndmpd_connect_close_v3(connection, (void *)NULL);
10612654012fSReza Sabdar 		break;
10622654012fSReza Sabdar 	default:
10632654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
10642654012fSReza Sabdar 		    "Invalid session (0x%p) version 0x%x", session,
10652654012fSReza Sabdar 		    session->ns_protocol_version);
10662654012fSReza Sabdar 	}
10672654012fSReza Sabdar 
10682654012fSReza Sabdar 	return (0);
10692654012fSReza Sabdar }
10702654012fSReza Sabdar 
10712654012fSReza Sabdar /*
10722654012fSReza Sabdar  * Get the list of all active sessions to the clients.
10732654012fSReza Sabdar  */
10742654012fSReza Sabdar void
ndmp_connect_list_get(ndmp_door_ctx_t * enc_ctx)10752654012fSReza Sabdar ndmp_connect_list_get(ndmp_door_ctx_t *enc_ctx)
10762654012fSReza Sabdar {
10772654012fSReza Sabdar 	int n;
10782654012fSReza Sabdar 	struct conn_list *clp;
10792654012fSReza Sabdar 
10802654012fSReza Sabdar 	n = 0;
10812654012fSReza Sabdar 	(void) mutex_lock(&cl_mutex);
10822654012fSReza Sabdar 	LIST_FOREACH(clp, &cl_head, cl_q) {
10832654012fSReza Sabdar 		n++;
10842654012fSReza Sabdar 	}
10852654012fSReza Sabdar 	/* write number of connections */
10862654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, n);
10872654012fSReza Sabdar 	n = 0;
10882654012fSReza Sabdar 	LIST_FOREACH(clp, &cl_head, cl_q) {
10892654012fSReza Sabdar 		connection_get(clp, enc_ctx);
10902654012fSReza Sabdar 		n++;
10912654012fSReza Sabdar 	}
10922654012fSReza Sabdar 	(void) mutex_unlock(&cl_mutex);
10932654012fSReza Sabdar }
10942654012fSReza Sabdar 
10952654012fSReza Sabdar /*
10962654012fSReza Sabdar  * ndmpd_connect_kill_id
10972654012fSReza Sabdar  *
10982654012fSReza Sabdar  * Find a connection by its id and kill it.
10992654012fSReza Sabdar  *
11002654012fSReza Sabdar  * Parameters:
11012654012fSReza Sabdar  *   id (input) - connection id.
11022654012fSReza Sabdar  *
11032654012fSReza Sabdar  * Returns:
11042654012fSReza Sabdar  *   0 - success
11052654012fSReza Sabdar  *  -1 - error
11062654012fSReza Sabdar  */
11072654012fSReza Sabdar int
ndmpd_connect_kill_id(int id)11082654012fSReza Sabdar ndmpd_connect_kill_id(int id)
11092654012fSReza Sabdar {
11102654012fSReza Sabdar 	struct conn_list *clp;
11112654012fSReza Sabdar 
11122654012fSReza Sabdar 	if (!(clp = ndmp_connect_list_find_id(id)))
11132654012fSReza Sabdar 		return (-1);
11142654012fSReza Sabdar 
11152654012fSReza Sabdar 	return (ndmpd_connect_kill(clp->cl_conn));
11162654012fSReza Sabdar }
11172654012fSReza Sabdar 
11182654012fSReza Sabdar /* Get the devices info */
11192654012fSReza Sabdar void
ndmpd_get_devs(ndmp_door_ctx_t * enc_ctx)11202654012fSReza Sabdar ndmpd_get_devs(ndmp_door_ctx_t *enc_ctx)
11212654012fSReza Sabdar {
11222654012fSReza Sabdar 	int i, n;
11232654012fSReza Sabdar 	sasd_drive_t *sd;
11242654012fSReza Sabdar 	scsi_link_t *slink;
11252654012fSReza Sabdar 
11262654012fSReza Sabdar 	if ((n = sasd_dev_count()) == 0) {
11272654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, n);
11282654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "No device attached.");
11292654012fSReza Sabdar 		return;
11302654012fSReza Sabdar 	}
11312654012fSReza Sabdar 	ndmp_door_put_int32(enc_ctx, n);
11322654012fSReza Sabdar 
11332654012fSReza Sabdar 	for (i = 0; i < n; i++) {
11342654012fSReza Sabdar 		sd = sasd_drive(i);
11352654012fSReza Sabdar 		slink = sasd_dev_slink(i);
11362654012fSReza Sabdar 
11372654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, slink->sl_type);
11382654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, sd->sd_name);
11392654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, slink->sl_lun);
11402654012fSReza Sabdar 		ndmp_door_put_int32(enc_ctx, slink->sl_sid);
11412654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, sd->sd_vendor);
11422654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, sd->sd_id);
11432654012fSReza Sabdar 		ndmp_door_put_string(enc_ctx, sd->sd_rev);
11447bc22e45SReza Sabdar 		ndmp_door_put_string(enc_ctx, sd->sd_serial);
11457bc22e45SReza Sabdar 		ndmp_door_put_string(enc_ctx, sd->sd_wwn);
11462654012fSReza Sabdar 	}
11472654012fSReza Sabdar }
11482654012fSReza Sabdar 
11492654012fSReza Sabdar /*
11502654012fSReza Sabdar  * ndmpd_connect_auth_text
11512654012fSReza Sabdar  *
11522654012fSReza Sabdar  * Checks text authorization.
11532654012fSReza Sabdar  *
11542654012fSReza Sabdar  * Parameters:
11552654012fSReza Sabdar  *   auth_id (input) - user name
11562654012fSReza Sabdar  *   auth_password(input) - password
11572654012fSReza Sabdar  *
11582654012fSReza Sabdar  * Returns:
11592654012fSReza Sabdar  *   NDMP_NO_ERR: on success
11602654012fSReza Sabdar  *   Other NDMP_ error: invalid user name and password
11612654012fSReza Sabdar  */
11622654012fSReza Sabdar int
ndmpd_connect_auth_text(char * uname,char * auth_id,char * auth_password)11632654012fSReza Sabdar ndmpd_connect_auth_text(char *uname, char *auth_id, char *auth_password)
11642654012fSReza Sabdar {
11652654012fSReza Sabdar 	char *passwd, *dec_passwd;
11662654012fSReza Sabdar 	int rv;
11672654012fSReza Sabdar 
11682654012fSReza Sabdar 	if (strcmp(uname, auth_id) != 0) {
11692654012fSReza Sabdar 		rv = NDMP_NOT_AUTHORIZED_ERR;
11702654012fSReza Sabdar 	} else {
11712654012fSReza Sabdar 		passwd = ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD);
11722654012fSReza Sabdar 		if (!passwd || !*passwd) {
11732654012fSReza Sabdar 			rv = NDMP_NOT_AUTHORIZED_ERR;
11742654012fSReza Sabdar 		} else {
11752654012fSReza Sabdar 			dec_passwd = ndmp_base64_decode(passwd);
11762654012fSReza Sabdar 			if (dec_passwd == NULL || *dec_passwd == 0)
11772654012fSReza Sabdar 				rv = NDMP_NOT_AUTHORIZED_ERR;
11782654012fSReza Sabdar 			else if (strcmp(auth_password, dec_passwd) != 0)
11792654012fSReza Sabdar 				rv = NDMP_NOT_AUTHORIZED_ERR;
11802654012fSReza Sabdar 			else
11812654012fSReza Sabdar 				rv = NDMP_NO_ERR;
11822654012fSReza Sabdar 
11832654012fSReza Sabdar 			free(dec_passwd);
11842654012fSReza Sabdar 		}
11852654012fSReza Sabdar 	}
11862654012fSReza Sabdar 
11872654012fSReza Sabdar 	if (rv == NDMP_NO_ERR) {
11882654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Authorization granted.");
11892654012fSReza Sabdar 	} else {
11902654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Authorization denied.");
11912654012fSReza Sabdar 	}
11922654012fSReza Sabdar 
11932654012fSReza Sabdar 	return (rv);
11942654012fSReza Sabdar }
11952654012fSReza Sabdar 
11962654012fSReza Sabdar 
11972654012fSReza Sabdar /*
11982654012fSReza Sabdar  * ndmpd_connect_auth_md5
11992654012fSReza Sabdar  *
12002654012fSReza Sabdar  * Checks MD5 authorization.
12012654012fSReza Sabdar  *
12022654012fSReza Sabdar  * Parameters:
12032654012fSReza Sabdar  *   auth_id (input) - user name
12042654012fSReza Sabdar  *   auth_digest(input) - MD5 digest
12052654012fSReza Sabdar  * 	This is a 16 bytes digest info which is a MD5 transform of 128 bytes
12062654012fSReza Sabdar  * 	message (password + padding + server challenge + password). Server
12072654012fSReza Sabdar  * 	challenge is a 64 bytes random string per NDMP session sent out to the
12082654012fSReza Sabdar  * 	client on demand (See NDMP_CONFIG_GET_AUTH_ATTR command).
12092654012fSReza Sabdar  *
12102654012fSReza Sabdar  * Returns:
12112654012fSReza Sabdar  *   NDMP_NO_ERR: on success
12122654012fSReza Sabdar  *   Other NDMP_ error: invalid user name and password
12132654012fSReza Sabdar  */
12142654012fSReza Sabdar int
ndmpd_connect_auth_md5(char * uname,char * auth_id,char * auth_digest,unsigned char * auth_challenge)12152654012fSReza Sabdar ndmpd_connect_auth_md5(char *uname, char *auth_id, char *auth_digest,
12162654012fSReza Sabdar     unsigned char *auth_challenge)
12172654012fSReza Sabdar {
12182654012fSReza Sabdar 	char *passwd, *dec_passwd;
12192654012fSReza Sabdar 	unsigned char digest[16];
12202654012fSReza Sabdar 	int rv;
12212654012fSReza Sabdar 
12222654012fSReza Sabdar 	if (strcmp(uname, auth_id) != 0) {
12232654012fSReza Sabdar 		rv = NDMP_NOT_AUTHORIZED_ERR;
12242654012fSReza Sabdar 	} else {
12252654012fSReza Sabdar 		passwd = ndmpd_get_prop(NDMP_CRAM_MD5_PASSWORD);
12262654012fSReza Sabdar 		if (passwd == NULL || *passwd == 0) {
12272654012fSReza Sabdar 			rv = NDMP_NOT_AUTHORIZED_ERR;
12282654012fSReza Sabdar 		} else {
12292654012fSReza Sabdar 			dec_passwd = ndmp_base64_decode(passwd);
12302654012fSReza Sabdar 
12312654012fSReza Sabdar 			if (dec_passwd == NULL || *dec_passwd == 0) {
12322654012fSReza Sabdar 				rv = NDMP_NOT_AUTHORIZED_ERR;
12332654012fSReza Sabdar 			} else {
12342654012fSReza Sabdar 				create_md5_digest(digest, dec_passwd,
12352654012fSReza Sabdar 				    auth_challenge);
12362654012fSReza Sabdar 				if (memcmp(digest, auth_digest,
12372654012fSReza Sabdar 				    sizeof (digest)) != 0) {
12382654012fSReza Sabdar 					rv = NDMP_NOT_AUTHORIZED_ERR;
12392654012fSReza Sabdar 				} else {
12402654012fSReza Sabdar 					rv = NDMP_NO_ERR;
12412654012fSReza Sabdar 				}
12422654012fSReza Sabdar 			}
12432654012fSReza Sabdar 			free(dec_passwd);
12442654012fSReza Sabdar 		}
12452654012fSReza Sabdar 	}
12462654012fSReza Sabdar 
12472654012fSReza Sabdar 	if (rv == NDMP_NO_ERR) {
12482654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Authorization granted.");
12492654012fSReza Sabdar 	} else {
12502654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Authorization denied.");
12512654012fSReza Sabdar 	}
12522654012fSReza Sabdar 
12532654012fSReza Sabdar 	return (rv);
12542654012fSReza Sabdar }
1255