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