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