2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
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
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
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.
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. */
43 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <sys/queue.h>
49 #include <arpa/inet.h>
54 #include "ndmpd_common.h"
57 #include <ndmpd_door.h>
58 #include <security/pam_appl.h>
61 static int ndmpd_connect_auth_text(char *uname
, char *auth_id
,
63 static int ndmpd_connect_auth_md5(char *uname
, char *auth_id
, char *auth_digest
,
64 unsigned char *auth_challenge
);
65 static struct conn_list
*ndmp_connect_list_find(ndmp_connection_t
*connection
);
66 static void create_md5_digest(unsigned char *digest
, char *passwd
,
67 unsigned char *challenge
);
68 static struct conn_list
*ndmp_connect_list_find_id(int id
);
70 /* routines for connection info */
71 void ndmp_connect_list_get(ndmp_door_ctx_t
*enc_ctx
);
72 static void connection_get(struct conn_list
*clp
, ndmp_door_ctx_t
*enc_ctx
);
73 static void ndmp_connect_get_conn(struct conn_list
*clp
,
74 ndmp_door_ctx_t
*enc_ctx
);
75 static void ndmp_connect_get_v2(ndmp_connection_t
*connection
,
76 ndmp_door_ctx_t
*enc_ctx
);
77 static void ndmp_connect_get_scsi_v2(ndmpd_session_t
*session
,
78 ndmp_door_ctx_t
*enc_ctx
);
79 static void ndmp_connect_get_tape_v2(ndmpd_session_t
*session
,
80 ndmp_door_ctx_t
*enc_ctx
);
81 static void ndmp_connect_get_mover_v2(ndmpd_session_t
*session
,
82 ndmp_door_ctx_t
*enc_ctx
);
83 static void ndmp_connect_get_data_v2(ndmpd_session_t
*session
,
84 ndmp_door_ctx_t
*enc_ctx
);
85 static void ndmp_connect_get_v3(ndmp_connection_t
*connection
,
86 ndmp_door_ctx_t
*enc_ctx
);
87 static void ndmp_connect_get_mover_v3(ndmpd_session_t
*session
,
88 ndmp_door_ctx_t
*enc_ctx
);
89 static void ndmp_connect_get_data_v3(ndmpd_session_t
*session
,
90 ndmp_door_ctx_t
*enc_ctx
);
91 void ndmpd_get_devs(ndmp_door_ctx_t
*enc_ctx
);
94 #define LIST_FOREACH(var, head, field) \
95 for ((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
96 #endif /* LIST_FOREACH */
99 * List of active connections.
102 LIST_ENTRY(conn_list
) cl_q
;
104 ndmp_connection_t
*cl_conn
;
106 LIST_HEAD(cl_head
, conn_list
);
109 * Head of the active connections.
111 static struct cl_head cl_head
;
113 mutex_t cl_mutex
= DEFAULTMUTEX
;
117 * Set this variable to non-zero to print verbose information.
119 int ndmp_connect_print_verbose
= 0;
123 * ************************************************************************
125 * ************************************************************************
129 * ndmpd_connect_open_v2
131 * This handler sets the protocol version to be used on the connection.
134 * connection (input) - connection handle.
135 * body (input) - request message body.
142 ndmpd_connect_open_v2(ndmp_connection_t
*connection
, void *body
)
144 ndmp_connect_open_request
*request
= (ndmp_connect_open_request
*)body
;
145 ndmp_connect_open_reply reply
;
146 ndmpd_session_t
*session
;
148 reply
.error
= NDMP_NO_ERR
;
150 if (!(session
= (ndmpd_session_t
*)ndmp_get_client_data(connection
)))
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
;
159 ndmp_send_reply(connection
, (void *) &reply
,
160 "sending connect_open reply");
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.
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
;
178 * ndmpd_connect_client_auth_v2
180 * This handler authorizes the NDMP connection.
183 * connection (input) - connection handle.
184 * msginfo (input) - request message.
190 ndmpd_connect_client_auth_v2(ndmp_connection_t
*connection
, void *body
)
192 ndmp_connect_client_auth_request
*request
;
193 ndmp_connect_client_auth_reply reply
;
194 ndmp_auth_text
*auth
;
195 ndmpd_session_t
*session
;
197 unsigned char md5_digest
[16];
198 char *passwd
, *dec_passwd
;
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" :
208 reply
.error
= NDMP_NO_ERR
;
210 switch (request
->auth_data
.auth_type
) {
213 * Allow no authorization for development.
214 * Comment the following for a non-secure production server.
216 NDMP_LOG(LOG_ERR
, "Authorization denied.");
218 "Authorization type should be md5 or cleartext.");
219 reply
.error
= NDMP_ILLEGAL_ARGS_ERR
;
220 ndmpd_audit_connect(connection
, EINVAL
);
224 /* Check authorization. */
225 if ((uname
= ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME
)) == NULL
||
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
);
237 auth
= &request
->auth_data
.ndmp_auth_data_u
.auth_text
;
238 if (strcmp(uname
, auth
->user
) != 0) {
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
);
246 passwd
= ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD
);
247 if (!passwd
|| !*passwd
) {
248 NDMP_LOG(LOG_ERR
, "Authorization denied.");
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
);
259 dec_passwd
= ndmp_base64_decode(passwd
);
261 if (!dec_passwd
|| !*dec_passwd
||
262 strcmp(auth
->password
, dec_passwd
) != 0) {
264 "Authorization denied. Invalid password.");
265 reply
.error
= NDMP_NOT_AUTHORIZED_ERR
;
267 NDMP_LOG(LOG_DEBUG
, "Authorization granted.");
269 ndmpd_audit_connect(connection
, reply
.error
?
270 ADT_FAIL_PAM
+ PAM_AUTH_ERR
: 0);
276 /* Check authorization. */
277 if ((uname
= ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME
)) == NULL
||
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
);
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
);
302 dec_passwd
= ndmp_base64_decode(passwd
);
304 session
= ndmp_get_client_data(connection
);
305 create_md5_digest(md5_digest
, dec_passwd
,
306 session
->ns_challenge
);
308 if (strcmp(uname
, md5
->user
) != 0) {
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) {
315 "Authorization denied. Invalid password.");
316 reply
.error
= NDMP_NOT_AUTHORIZED_ERR
;
318 NDMP_LOG(LOG_DEBUG
, "Authorization granted");
320 ndmpd_audit_connect(connection
, reply
.error
?
321 ADT_FAIL_PAM
+ PAM_AUTH_ERR
: 0);
327 reply
.error
= NDMP_ILLEGAL_ARGS_ERR
;
330 if (reply
.error
== NDMP_NO_ERR
)
331 ndmp_set_authorized(connection
, TRUE
);
333 ndmp_set_authorized(connection
, FALSE
);
335 ndmp_send_reply(connection
, (void *) &reply
,
336 "sending ndmp_connect_client_auth reply");
341 * ndmpd_connect_server_auth_v2
343 * This handler authenticates the server to the client.
346 * connection (input) - connection handle.
347 * msginfo (input) - request message.
353 ndmpd_connect_server_auth_v2(ndmp_connection_t
*connection
, void *body
)
355 ndmp_connect_server_auth_request
*request
;
356 ndmp_connect_server_auth_reply reply
;
358 request
= (ndmp_connect_server_auth_request
*)body
;
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" :
366 reply
.error
= NDMP_NO_ERR
;
367 reply
.auth_result
.auth_type
= request
->client_attr
.auth_type
;
368 switch (request
->client_attr
.auth_type
) {
373 reply
.auth_result
.ndmp_auth_data_u
.auth_text
.user
= "ndmpd";
374 reply
.auth_result
.ndmp_auth_data_u
.auth_text
.password
=
379 reply
.error
= NDMP_ILLEGAL_ARGS_ERR
;
383 reply
.error
= NDMP_ILLEGAL_ARGS_ERR
;
386 ndmp_send_reply(connection
, (void *) &reply
,
387 "sending ndmp_connect_auth reply");
392 * ndmpd_connect_close_v2
394 * This handler closes the connection.
397 * connection (input) - connection handle.
398 * msginfo (input) - request message.
405 ndmpd_connect_close_v2(ndmp_connection_t
*connection
, void *body
)
407 ndmpd_session_t
*session
;
409 if ((session
= (ndmpd_session_t
*)ndmp_get_client_data(connection
))) {
410 (void) ndmp_close(connection
);
411 session
->ns_eof
= TRUE
;
416 * ************************************************************************
418 * ************************************************************************
422 * ndmpd_connect_client_auth_v3
424 * This handler authorizes the NDMP connection.
427 * connection (input) - connection handle.
428 * msginfo (input) - request message.
434 ndmpd_connect_client_auth_v3(ndmp_connection_t
*connection
, void *body
)
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
;
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");
451 reply
.error
= NDMP_NO_ERR
;
453 switch (request
->auth_data
.auth_type
) {
456 reply
.error
= NDMP_NOT_SUPPORTED_ERR
;
457 ndmpd_audit_connect(connection
, ENOTSUP
);
461 /* Check authorization. */
462 if ((uname
= ndmpd_get_prop(NDMP_CLEARTEXT_USERNAME
)) == NULL
||
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
);
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);
483 /* Check authorization. */
484 if ((uname
= ndmpd_get_prop(NDMP_CRAM_MD5_USERNAME
)) == NULL
||
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
);
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);
507 reply
.error
= NDMP_ILLEGAL_ARGS_ERR
;
508 ndmpd_audit_connect(connection
, EINVAL
);
511 if (reply
.error
== NDMP_NO_ERR
) {
512 ndmp_set_authorized(connection
, TRUE
);
514 ndmp_set_authorized(connection
, FALSE
);
515 if (tcp_get_peer(connection
->conn_sock
, &addr
.s_addr
,
518 "Authorization(%s) denied for %s.", type
,
519 inet_ntoa(IN_ADDR(addr
)));
523 ndmp_send_reply(connection
, (void *) &reply
,
524 "sending ndmp_connect_auth reply");
529 * ndmpd_connect_close_v3
531 * Close the connection to the DMA.
532 * Send the SHUTDOWN message before closing the socket connection to the DMA.
535 * connection (input) - connection handle.
536 * msginfo (input) - request message.
543 ndmpd_connect_close_v3(ndmp_connection_t
*connection
, void *body
)
545 ndmpd_session_t
*session
;
546 ndmp_lbr_params_t
*nlp
;
547 ndmp_notify_connected_request req
;
549 if (!(session
= (ndmpd_session_t
*)ndmp_get_client_data(connection
)))
551 if ((nlp
= ndmp_get_nlp(session
)) == NULL
)
554 NDMP_LOG(LOG_DEBUG
, "ver: %u",
555 session
->ns_protocol_version
);
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.";
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");
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
);
576 * ************************************************************************
578 * ************************************************************************
582 * ************************************************************************
584 * ************************************************************************
590 * This function uses the MD5 message-digest algorithm described
591 * in RFC1321 to authenticate the client using a shared secret (password).
592 * The message used to compute the MD5 digest is a concatenation of password,
593 * null padding, the 64 byte fixed length challenge and a repeat of the
594 * password. The length of the null padding is chosen to result in a 128 byte
595 * fixed length message. The lengh of the padding can be computed as
596 * 64 - 2*(length of the password). The client digest is computed using the
597 * server challenge from the NDMP_CONFIG_GET_AUTH_ATTR reply.
600 * digest (output) - 16 bytes MD5 digest
601 * passwd (input) - user password
602 * challenge (input) - 64 bytes server challenge
608 create_md5_digest(unsigned char *digest
, char *passwd
, unsigned char *challenge
)
618 if ((len
= strlen(pwd
)) > MD5_PASS_LIMIT
)
619 len
= MD5_PASS_LIMIT
;
620 (void) memcpy(p
, pwd
, len
);
623 for (i
= 0; i
< MD5_CHALLENGE_SIZE
- 2 * len
; i
++)
626 (void) memcpy(p
, challenge
, MD5_CHALLENGE_SIZE
);
627 p
+= MD5_CHALLENGE_SIZE
;
628 (void) strlcpy(p
, pwd
, MD5_PASS_LIMIT
);
631 MD5Update(&md
, buf
, 128);
632 MD5Final(digest
, &md
);
636 * ndmp_connect_list_find
638 * Find the element in the active connection list.
641 * connection (input) - connection handler.
645 * connection list element pointer
647 static struct conn_list
*
648 ndmp_connect_list_find(ndmp_connection_t
*connection
)
650 struct conn_list
*clp
;
652 NDMP_LOG(LOG_DEBUG
, "connection: 0x%p",
655 LIST_FOREACH(clp
, &cl_head
, cl_q
) {
656 if (clp
->cl_conn
== connection
) {
657 (void) mutex_unlock(&cl_mutex
);
665 * ndmpconnect_list_add
667 * Add the new connection to the list of the active connections.
670 * connection (input) - connection handler.
671 * id (input/output) - pointer to connection id.
678 ndmp_connect_list_add(ndmp_connection_t
*connection
, int *id
)
680 struct conn_list
*clp
;
682 if (connection
== NULL
) {
683 NDMP_LOG(LOG_DEBUG
, "Invalid argument");
687 if ((clp
= ndmp_malloc(sizeof (struct conn_list
))) == NULL
)
690 clp
->cl_conn
= connection
;
693 (void) mutex_lock(&cl_mutex
);
694 LIST_INSERT_HEAD(&cl_head
, clp
, cl_q
);
696 (void) mutex_unlock(&cl_mutex
);
702 * ndmp_connect_list_del
704 * Delete the specified connection from the list.
707 * connection (input) - connection handler.
714 ndmp_connect_list_del(ndmp_connection_t
*connection
)
716 struct conn_list
*clp
;
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");
725 LIST_REMOVE(clp
, cl_q
);
726 (void) mutex_unlock(&cl_mutex
);
734 * ndmpconnect_list_find_id
736 * Find the element specified by its id in the list of active connections.
739 * id (input) - connection id.
743 * connection list element pointer
745 static struct conn_list
*
746 ndmp_connect_list_find_id(int id
)
748 struct conn_list
*clp
;
750 NDMP_LOG(LOG_DEBUG
, "id: %d", id
);
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
);
760 (void) mutex_unlock(&cl_mutex
);
765 * Get common fields of the active connection.
768 ndmp_connect_get_conn(struct conn_list
*clp
, ndmp_door_ctx_t
*enc_ctx
)
772 char cl_addr
[NDMP_CL_ADDR_LEN
];
773 ndmpd_session_t
*session
;
775 if (!(session
= (ndmpd_session_t
*)ndmp_get_client_data(clp
->cl_conn
)))
778 ndmp_door_put_int32(enc_ctx
, clp
->cl_id
);
779 ndmp_door_put_int32(enc_ctx
, session
->ns_protocol_version
);
780 ndmp_door_put_int32(enc_ctx
, clp
->cl_conn
->conn_authorized
);
781 ndmp_door_put_int32(enc_ctx
, session
->ns_eof
);
782 if (tcp_get_peer(clp
->cl_conn
->conn_sock
, &(addr
.s_addr
), &port
) != -1)
783 (void) snprintf(cl_addr
, NDMP_CL_ADDR_LEN
, "%s:%d",
784 (char *)inet_ntoa(addr
), port
);
787 ndmp_door_put_string(enc_ctx
, cl_addr
);
791 * Get the connection SCSI info.
794 ndmp_connect_get_scsi_v2(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
796 ndmp_door_put_int32(enc_ctx
, session
->ns_scsi
.sd_is_open
);
797 ndmp_door_put_string(enc_ctx
, session
->ns_scsi
.sd_adapter_name
);
798 ndmp_door_put_int32(enc_ctx
, session
->ns_scsi
.sd_valid_target_set
);
799 if (session
->ns_scsi
.sd_valid_target_set
) {
800 ndmp_door_put_int32(enc_ctx
, session
->ns_scsi
.sd_sid
);
801 ndmp_door_put_int32(enc_ctx
, session
->ns_scsi
.sd_lun
);
806 * Get the connection tape info.
809 ndmp_connect_get_tape_v2(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
811 char dev_name
[NDMP_TAPE_DEV_NAME
];
813 ndmp_door_put_int32(enc_ctx
, session
->ns_tape
.td_fd
);
814 if (session
->ns_tape
.td_fd
!= -1) {
815 ndmp_door_put_uint64(enc_ctx
, session
->ns_tape
.td_record_count
);
816 ndmp_door_put_int32(enc_ctx
, session
->ns_tape
.td_mode
);
817 (void) snprintf(dev_name
, NDMP_TAPE_DEV_NAME
, "%st%02x%x",
818 session
->ns_tape
.td_adapter_name
, session
->ns_tape
.td_sid
,
819 session
->ns_tape
.td_lun
);
820 ndmp_door_put_string(enc_ctx
, dev_name
);
821 ndmp_door_put_string(enc_ctx
, session
->ns_tape
.td_adapter_name
);
822 ndmp_door_put_int32(enc_ctx
, session
->ns_tape
.td_sid
);
823 ndmp_door_put_int32(enc_ctx
, session
->ns_tape
.td_lun
);
828 * Get the connection mover info.
831 ndmp_connect_get_mover_v2(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
833 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_state
);
834 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_mode
);
835 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_pause_reason
);
836 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_halt_reason
);
837 ndmp_door_put_uint64(enc_ctx
, session
->ns_mover
.md_record_size
);
838 ndmp_door_put_uint64(enc_ctx
, session
->ns_mover
.md_record_num
);
839 ndmp_door_put_uint64(enc_ctx
, session
->ns_mover
.md_position
);
840 ndmp_door_put_uint64(enc_ctx
, session
->ns_mover
.md_window_offset
);
841 ndmp_door_put_uint64(enc_ctx
, session
->ns_mover
.md_window_length
);
842 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_sock
);
846 * Get the connection common data info.
849 ndmp_connect_get_data_common(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
855 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_operation
);
856 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_state
);
857 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_halt_reason
);
858 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_sock
);
859 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_mover
.addr_type
);
860 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_abort
);
861 ndmp_door_put_uint64(enc_ctx
, session
->ns_data
.dd_read_offset
);
862 ndmp_door_put_uint64(enc_ctx
, session
->ns_data
.dd_read_length
);
863 ndmp_door_put_uint64(enc_ctx
, session
->ns_data
.dd_data_size
);
864 /* verify data.env has as much data as in session->ns_data.dd_env_len */
866 ep
= session
->ns_data
.dd_env
;
867 for (i
= 0; ep
&& i
< session
->ns_data
.dd_env_len
; i
++, ep
++)
871 (void) mutex_lock(&session
->ns_lock
);
872 ndmp_door_put_uint64(enc_ctx
, len
);
873 ep
= session
->ns_data
.dd_env
;
874 for (i
= 0; i
< len
; i
++, ep
++) {
875 ndmp_door_put_string(enc_ctx
, ep
->name
);
876 ndmp_door_put_string(enc_ctx
, ep
->value
);
878 (void) mutex_unlock(&session
->ns_lock
);
882 * Get the connection data info.
885 ndmp_connect_get_data_v2(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
889 char tcp_addr
[NDMP_TCP_ADDR_SIZE
];
891 ndmp_connect_get_data_common(session
, enc_ctx
);
893 switch (session
->ns_data
.dd_mover
.addr_type
) {
894 case NDMP_ADDR_LOCAL
:
895 (void) snprintf(tcp_addr
, NDMP_TCP_ADDR_SIZE
, "%s", "Local");
896 ndmp_door_put_string(enc_ctx
, tcp_addr
);
899 (void) snprintf(tcp_addr
, NDMP_TCP_ADDR_SIZE
, "%s:%d",
900 (char *)inet_ntoa(IN_ADDR(
901 session
->ns_data
.dd_mover
.ndmp_mover_addr_u
.addr
.ip_addr
)),
902 session
->ns_data
.dd_mover
.ndmp_mover_addr_u
.addr
.port
);
903 ndmp_door_put_string(enc_ctx
, tcp_addr
);
906 (void) snprintf(tcp_addr
, NDMP_TCP_ADDR_SIZE
, "%s", "Unknown");
907 ndmp_door_put_string(enc_ctx
, tcp_addr
);
910 ndmp_door_put_uint64(enc_ctx
, session
->ns_data
.dd_nlist_len
);
911 np
= session
->ns_data
.dd_nlist
;
912 for (i
= 0; np
&& i
< (int)session
->ns_data
.dd_nlist_len
; i
++, np
++) {
913 ndmp_door_put_string(enc_ctx
, np
->name
);
914 ndmp_door_put_string(enc_ctx
, np
->dest
);
919 * Get V2 connection info.
922 ndmp_connect_get_v2(ndmp_connection_t
*connection
, ndmp_door_ctx_t
*enc_ctx
)
924 ndmpd_session_t
*session
;
926 if ((session
= (ndmpd_session_t
*)ndmp_get_client_data(connection
))) {
927 ndmp_connect_get_scsi_v2(session
, enc_ctx
);
928 ndmp_connect_get_tape_v2(session
, enc_ctx
);
929 ndmp_connect_get_mover_v2(session
, enc_ctx
);
930 ndmp_connect_get_data_v2(session
, enc_ctx
);
935 * Get the V3 connection mover info.
938 ndmp_connect_get_mover_v3(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
940 char tcp_addr
[NDMP_TCP_ADDR_SIZE
];
942 /* get all the V2 mover data first */
943 ndmp_connect_get_mover_v2(session
, enc_ctx
);
945 /* get the V3 mover data now */
946 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_listen_sock
);
947 ndmp_door_put_int32(enc_ctx
, session
->ns_mover
.md_data_addr
.addr_type
);
949 (void) snprintf(tcp_addr
, NDMP_TCP_ADDR_SIZE
, "%s:%d",
951 inet_ntoa(IN_ADDR(session
->ns_mover
.md_data_addr
.tcp_ip_v3
)),
952 (int)session
->ns_mover
.md_data_addr
.tcp_port_v3
);
953 ndmp_door_put_string(enc_ctx
, tcp_addr
);
957 * Get the connection data info.
960 ndmp_connect_get_data_v3(ndmpd_session_t
*session
, ndmp_door_ctx_t
*enc_ctx
)
963 mem_ndmp_name_v3_t
*np
;
964 char tcp_addr
[NDMP_TCP_ADDR_SIZE
];
966 ndmp_connect_get_data_common(session
, enc_ctx
);
968 (void) snprintf(tcp_addr
, NDMP_TCP_ADDR_SIZE
, "%s:%d",
969 (char *)inet_ntoa(IN_ADDR(session
->ns_data
.dd_data_addr
.tcp_ip_v3
)),
970 (int)session
->ns_data
.dd_data_addr
.tcp_port_v3
);
971 ndmp_door_put_string(enc_ctx
, tcp_addr
);
972 ndmp_door_put_int32(enc_ctx
, session
->ns_data
.dd_listen_sock
);
973 ndmp_door_put_uint64(enc_ctx
,
974 session
->ns_data
.dd_module
.dm_stats
.ms_bytes_processed
);
975 ndmp_door_put_uint64(enc_ctx
, session
->ns_data
.dd_nlist_len
);
976 np
= session
->ns_data
.dd_nlist_v3
;
977 for (i
= 0; np
&& i
< (int)session
->ns_data
.dd_nlist_len
; i
++, np
++) {
978 ndmp_door_put_string(enc_ctx
, np
->nm3_opath
);
979 ndmp_door_put_string(enc_ctx
, np
->nm3_dpath
);
980 ndmp_door_put_uint64(enc_ctx
, np
->nm3_node
);
981 ndmp_door_put_uint64(enc_ctx
, np
->nm3_fh_info
);
986 * Get V3 connection info.
989 ndmp_connect_get_v3(ndmp_connection_t
*connection
, ndmp_door_ctx_t
*enc_ctx
)
991 ndmpd_session_t
*session
;
993 if ((session
= (ndmpd_session_t
*)ndmp_get_client_data(connection
))) {
994 ndmp_connect_get_scsi_v2(session
, enc_ctx
);
995 ndmp_connect_get_tape_v2(session
, enc_ctx
);
996 ndmp_connect_get_mover_v3(session
, enc_ctx
);
997 ndmp_connect_get_data_v3(session
, enc_ctx
);
1002 * Get the list of all active sessions to the clients. For each version,
1003 * call the appropriate get function.
1006 connection_get(struct conn_list
*clp
, ndmp_door_ctx_t
*enc_ctx
)
1008 ndmpd_session_t
*session
;
1010 session
= (ndmpd_session_t
*)ndmp_get_client_data(clp
->cl_conn
);
1012 ndmp_door_put_int32(enc_ctx
, NDMP_SESSION_NODATA
);
1015 ndmp_door_put_int32(enc_ctx
, NDMP_SESSION_DATA
);
1017 switch (session
->ns_protocol_version
) {
1019 ndmp_connect_get_conn(clp
, enc_ctx
);
1020 ndmp_connect_get_v2(clp
->cl_conn
, enc_ctx
);
1024 ndmp_connect_get_conn(clp
, enc_ctx
);
1025 ndmp_connect_get_v3(clp
->cl_conn
, enc_ctx
);
1029 "Invalid session (0x%p) version 0x%x", session
,
1030 session
->ns_protocol_version
);
1035 * ndmpd_connect_kill
1037 * Kill the connection based on its version.
1040 * connection (input) - connection handler.
1047 ndmpd_connect_kill(ndmp_connection_t
*connection
)
1049 ndmpd_session_t
*session
;
1051 if (!(session
= (ndmpd_session_t
*)ndmp_get_client_data(connection
)))
1054 switch (session
->ns_protocol_version
) {
1056 ndmpd_connect_close_v2(connection
, NULL
);
1060 ndmpd_connect_close_v3(connection
, NULL
);
1064 "Invalid session (0x%p) version 0x%x", session
,
1065 session
->ns_protocol_version
);
1072 * Get the list of all active sessions to the clients.
1075 ndmp_connect_list_get(ndmp_door_ctx_t
*enc_ctx
)
1078 struct conn_list
*clp
;
1081 (void) mutex_lock(&cl_mutex
);
1082 LIST_FOREACH(clp
, &cl_head
, cl_q
) {
1085 /* write number of connections */
1086 ndmp_door_put_int32(enc_ctx
, n
);
1088 LIST_FOREACH(clp
, &cl_head
, cl_q
) {
1089 connection_get(clp
, enc_ctx
);
1092 (void) mutex_unlock(&cl_mutex
);
1096 * ndmpd_connect_kill_id
1098 * Find a connection by its id and kill it.
1101 * id (input) - connection id.
1108 ndmpd_connect_kill_id(int id
)
1110 struct conn_list
*clp
;
1112 if (!(clp
= ndmp_connect_list_find_id(id
)))
1115 return (ndmpd_connect_kill(clp
->cl_conn
));
1118 /* Get the devices info */
1120 ndmpd_get_devs(ndmp_door_ctx_t
*enc_ctx
)
1126 if ((n
= sasd_dev_count()) == 0) {
1127 ndmp_door_put_int32(enc_ctx
, n
);
1128 NDMP_LOG(LOG_DEBUG
, "No device attached.");
1131 ndmp_door_put_int32(enc_ctx
, n
);
1133 for (i
= 0; i
< n
; i
++) {
1135 slink
= sasd_dev_slink(i
);
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
);
1150 * ndmpd_connect_auth_text
1152 * Checks text authorization.
1155 * auth_id (input) - user name
1156 * auth_password(input) - password
1159 * NDMP_NO_ERR: on success
1160 * Other NDMP_ error: invalid user name and password
1163 ndmpd_connect_auth_text(char *uname
, char *auth_id
, char *auth_password
)
1165 char *passwd
, *dec_passwd
;
1168 if (strcmp(uname
, auth_id
) != 0) {
1169 rv
= NDMP_NOT_AUTHORIZED_ERR
;
1171 passwd
= ndmpd_get_prop(NDMP_CLEARTEXT_PASSWORD
);
1172 if (!passwd
|| !*passwd
) {
1173 rv
= NDMP_NOT_AUTHORIZED_ERR
;
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
;
1187 if (rv
== NDMP_NO_ERR
) {
1188 NDMP_LOG(LOG_DEBUG
, "Authorization granted.");
1190 NDMP_LOG(LOG_ERR
, "Authorization denied.");
1198 * ndmpd_connect_auth_md5
1200 * Checks MD5 authorization.
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).
1211 * NDMP_NO_ERR: on success
1212 * Other NDMP_ error: invalid user name and password
1215 ndmpd_connect_auth_md5(char *uname
, char *auth_id
, char *auth_digest
,
1216 unsigned char *auth_challenge
)
1218 char *passwd
, *dec_passwd
;
1219 unsigned char digest
[16];
1222 if (strcmp(uname
, auth_id
) != 0) {
1223 rv
= NDMP_NOT_AUTHORIZED_ERR
;
1225 passwd
= ndmpd_get_prop(NDMP_CRAM_MD5_PASSWORD
);
1226 if (passwd
== NULL
|| *passwd
== 0) {
1227 rv
= NDMP_NOT_AUTHORIZED_ERR
;
1229 dec_passwd
= ndmp_base64_decode(passwd
);
1231 if (dec_passwd
== NULL
|| *dec_passwd
== 0) {
1232 rv
= NDMP_NOT_AUTHORIZED_ERR
;
1234 create_md5_digest(digest
, dec_passwd
,
1236 if (memcmp(digest
, auth_digest
,
1237 sizeof (digest
)) != 0) {
1238 rv
= NDMP_NOT_AUTHORIZED_ERR
;
1247 if (rv
== NDMP_NO_ERR
) {
1248 NDMP_LOG(LOG_DEBUG
, "Authorization granted.");
1250 NDMP_LOG(LOG_ERR
, "Authorization denied.");