/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* BSD 3 Clause License
*
* Copyright (c) 2007, The Storage Networking Industry Association.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* distribution.
*
* - Neither the name of The Storage Networking Industry Association (SNIA)
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Copyright (c) 2007, The Storage Networking Industry Association. */
/* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
/* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
#include <errno.h>
#include <pwd.h>
#include <md5.h>
#include <shadow.h>
#include <crypt.h>
#include <alloca.h>
#include "ndmpd_common.h"
#include "ndmpd.h"
#include <libndmp.h>
#include <ndmpd_door.h>
#include <security/pam_appl.h>
char *auth_password);
unsigned char *auth_challenge);
unsigned char *challenge);
/* routines for connection info */
#ifndef LIST_FOREACH
#endif /* LIST_FOREACH */
/*
* List of active connections.
*/
struct conn_list {
int cl_id;
};
/*
* Head of the active connections.
*/
/*
* Set this variable to non-zero to print verbose information.
*/
int ndmp_connect_print_verbose = 0;
/*
* ************************************************************************
* NDMP V2 HANDLERS
* ************************************************************************
*/
/*
* ndmpd_connect_open_v2
*
* This handler sets the protocol version to be used on the connection.
*
* Parameters:
* connection (input) - connection handle.
* body (input) - request message body.
*
* Returns:
* void
*/
void
{
return;
"sending connect_open reply");
/*
* Set the protocol version.
* Must wait until after sending the reply since the reply
* must be sent using the same protocol version that was used
* to process the request.
*/
}
}
/*
* ndmpd_connect_client_auth_v2
*
* This handler authorizes the NDMP connection.
*
* Parameters:
* connection (input) - connection handle.
* msginfo (input) - request message.
*
* Returns:
* void
*/
void
{
char *uname;
"Invalid")));
case NDMP_AUTH_NONE:
/*
* Allow no authorization for development.
* Comment the following for a non-secure production server.
*/
"Authorization type should be md5 or cleartext.");
break;
case NDMP_AUTH_TEXT:
/* Check authorization. */
*uname == 0) {
"sending ndmp_connect_client_auth reply");
return;
}
"Authorization denied. Not a valid user.");
break;
}
"Cleartext password is not set at server.");
"sending ndmp_connect_client_auth reply");
return;
} else {
}
if (!dec_passwd || !*dec_passwd ||
"Authorization denied. Invalid password.");
} else {
}
ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
break;
case NDMP_AUTH_MD5:
/* Check authorization. */
*uname == 0) {
"sending ndmp_connect_client_auth reply");
return;
}
"sending ndmp_connect_client_auth reply");
return;
} else {
}
"Authorization denied. Not a valid user.");
sizeof (md5_digest)) != 0) {
"Authorization denied. Invalid password.");
} else {
}
ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
break;
default:
}
else
"sending ndmp_connect_client_auth reply");
}
/*
* ndmpd_connect_server_auth_v2
*
* This handler authenticates the server to the client.
*
* Parameters:
* connection (input) - connection handle.
* msginfo (input) - request message.
*
* Returns:
* void
*/
void
{
"Invalid")));
case NDMP_AUTH_NONE:
break;
case NDMP_AUTH_TEXT:
"ndmpsdk";
break;
case NDMP_AUTH_MD5:
break;
default:
}
"sending ndmp_connect_auth reply");
}
/*
* ndmpd_connect_close_v2
*
* This handler closes the connection.
*
* Parameters:
* connection (input) - connection handle.
* msginfo (input) - request message.
*
* Returns:
* void
*/
/*ARGSUSED*/
void
{
(void) ndmp_close(connection);
}
}
/*
* ************************************************************************
* NDMP V3 HANDLERS
* ************************************************************************
*/
/*
* ndmpd_connect_client_auth_v3
*
* This handler authorizes the NDMP connection.
*
* Parameters:
* connection (input) - connection handle.
* msginfo (input) - request message.
*
* Returns:
* void
*/
void
{
char *uname;
char *type;
case NDMP_AUTH_NONE:
type = "none";
break;
case NDMP_AUTH_TEXT:
/* Check authorization. */
*uname == 0) {
"sending ndmp_connect_client_auth reply");
return;
}
type = "text";
ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
break;
case NDMP_AUTH_MD5:
/* Check authorization. */
*uname == 0) {
"sending ndmp_connect_client_auth reply");
return;
}
type = "md5";
ADT_FAIL_PAM + PAM_AUTH_ERR : 0);
break;
default:
type = "unknown";
}
} else {
NULL) != -1) {
"Authorization(%s) denied for %s.", type,
}
}
"sending ndmp_connect_auth reply");
}
/*
* ndmpd_connect_close_v3
*
* Close the connection to the DMA.
* Send the SHUTDOWN message before closing the socket connection to the DMA.
*
* Parameters:
* connection (input) - connection handle.
* msginfo (input) - request message.
*
* Returns:
* void
*/
/*ARGSUSED*/
void
{
return;
return;
/* Send the SHUTDOWN message before closing the connection. */
NDMP_NO_ERR, (void *) &req, 0) < 0) {
return;
}
}
/*
* ************************************************************************
* NDMP V4 HANDLERS
* ************************************************************************
*/
/*
* ************************************************************************
* LOCALS
* ************************************************************************
*/
/*
* create_md5_digest
*
* This function uses the MD5 message-digest algorithm described
* in RFC1321 to authenticate the client using a shared secret (password).
* The message used to compute the MD5 digest is a concatenation of password,
* null padding, the 64 byte fixed length challenge and a repeat of the
* password. The length of the null padding is chosen to result in a 128 byte
* fixed length message. The lengh of the padding can be computed as
* 64 - 2*(length of the password). The client digest is computed using the
* server challenge from the NDMP_CONFIG_GET_AUTH_ATTR reply.
*
* Parameters:
* digest (output) - 16 bytes MD5 digest
* passwd (input) - user password
* challenge (input) - 64 bytes server challenge
*
* Returns:
* void
*/
static void
{
char *p = &buf[0];
int len, i;
char *pwd;
*p = 0;
p += len;
*p++ = 0;
p += MD5_CHALLENGE_SIZE;
}
/*
* ndmp_connect_list_find
*
* Find the element in the active connection list.
*
* Parameters:
* connection (input) - connection handler.
*
* Returns:
* NULL - error
* connection list element pointer
*/
static struct conn_list *
{
(void) mutex_unlock(&cl_mutex);
return (clp);
}
}
return (NULL);
}
/*
* ndmpconnect_list_add
*
* Add the new connection to the list of the active connections.
*
* Parameters:
* connection (input) - connection handler.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
if (connection == NULL) {
return (-1);
}
return (-1);
(void) mutex_lock(&cl_mutex);
(*id)++;
(void) mutex_unlock(&cl_mutex);
return (0);
}
/*
* ndmp_connect_list_del
*
* Delete the specified connection from the list.
*
* Parameters:
* connection (input) - connection handler.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
(void) mutex_lock(&cl_mutex);
(void) mutex_unlock(&cl_mutex);
return (-1);
}
(void) mutex_unlock(&cl_mutex);
return (0);
}
/*
* ndmpconnect_list_find_id
*
* Find the element specified by its id in the list of active connections.
*
* Parameters:
* id (input) - connection id.
*
* Returns:
* NULL - error
* connection list element pointer
*/
static struct conn_list *
{
(void) mutex_lock(&cl_mutex);
(void) mutex_unlock(&cl_mutex);
return (clp);
}
}
(void) mutex_unlock(&cl_mutex);
return (NULL);
}
/*
* Get common fields of the active connection.
*/
static void
{
int port;
return;
else
cl_addr[0] = '\0';
}
/*
* Get the connection SCSI info.
*/
static void
{
}
}
/*
* Get the connection tape info.
*/
static void
{
}
}
/*
* Get the connection mover info.
*/
static void
{
}
/*
* Get the connection common data info.
*/
static void
{
int i;
int len;
/* verify data.env has as much data as in session->ns_data.dd_env_len */
len = 0;
len++;
/* put the len */
}
}
/*
* Get the connection data info.
*/
static void
{
int i;
case NDMP_ADDR_LOCAL:
break;
case NDMP_ADDR_TCP:
break;
default:
}
}
}
/*
* Get V2 connection info.
*/
static void
{
}
}
/*
* Get the V3 connection mover info.
*/
static void
{
/* get all the V2 mover data first */
/* get the V3 mover data now */
tcp_addr[0] = '\0';
(char *)
}
/*
* Get the connection data info.
*/
static void
{
ulong_t i;
}
}
/*
* Get V3 connection info.
*/
static void
{
}
}
/*
* Get the list of all active sessions to the clients. For each version,
* call the appropriate get function.
*/
static void
{
if (!session) {
return;
}
switch (session->ns_protocol_version) {
case NDMPV2:
break;
case NDMPV3:
case NDMPV4:
break;
default:
"Invalid session (0x%p) version 0x%x", session,
}
}
/*
* ndmpd_connect_kill
*
* Kill the connection based on its version.
*
* Parameters:
* connection (input) - connection handler.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
return (-1);
switch (session->ns_protocol_version) {
case NDMPV2:
break;
case NDMPV3:
case NDMPV4:
break;
default:
"Invalid session (0x%p) version 0x%x", session,
}
return (0);
}
/*
* Get the list of all active sessions to the clients.
*/
void
{
int n;
n = 0;
(void) mutex_lock(&cl_mutex);
n++;
}
/* write number of connections */
n = 0;
n++;
}
(void) mutex_unlock(&cl_mutex);
}
/*
* ndmpd_connect_kill_id
*
* Find a connection by its id and kill it.
*
* Parameters:
* id (input) - connection id.
*
* Returns:
* 0 - success
* -1 - error
*/
int
{
return (-1);
}
/* Get the devices info */
void
{
int i, n;
if ((n = sasd_dev_count()) == 0) {
return;
}
for (i = 0; i < n; i++) {
sd = sasd_drive(i);
slink = sasd_dev_slink(i);
}
}
/*
* ndmpd_connect_auth_text
*
* Checks text authorization.
*
* Parameters:
* auth_id (input) - user name
* auth_password(input) - password
*
* Returns:
* NDMP_NO_ERR: on success
* Other NDMP_ error: invalid user name and password
*/
int
{
int rv;
} else {
} else {
else
rv = NDMP_NO_ERR;
}
}
if (rv == NDMP_NO_ERR) {
} else {
}
return (rv);
}
/*
* ndmpd_connect_auth_md5
*
* Checks MD5 authorization.
*
* Parameters:
* auth_id (input) - user name
* auth_digest(input) - MD5 digest
* This is a 16 bytes digest info which is a MD5 transform of 128 bytes
* message (password + padding + server challenge + password). Server
* challenge is a 64 bytes random string per NDMP session sent out to the
* client on demand (See NDMP_CONFIG_GET_AUTH_ATTR command).
*
* Returns:
* NDMP_NO_ERR: on success
* Other NDMP_ error: invalid user name and password
*/
int
unsigned char *auth_challenge)
{
int rv;
} else {
} else {
} else {
sizeof (digest)) != 0) {
} else {
rv = NDMP_NO_ERR;
}
}
}
}
if (rv == NDMP_NO_ERR) {
} else {
}
return (rv);
}