/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* SMB specific functions
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <zone.h>
#include <errno.h>
#include <locale.h>
#include <signal.h>
#include <fcntl.h>
#include <syslog.h>
#include "libshare.h"
#include "libshare_impl.h"
#include <pwd.h>
#include <limits.h>
#include <libscf.h>
#include <strings.h>
#include "libshare_smbfs.h"
#include <rpcsvc/daemon_utils.h>
/* internal functions */
static uint64_t smbfs_features();
static int smbfs_init();
static void smbfs_fini();
static int smbfs_set_proto_prop(sa_property_t);
static sa_protocol_properties_t smbfs_get_proto_set();
static char *smbfs_get_status();
static int smbfs_delete_section(char *);
static int smbfs_delete_property_group(char *);
static int range_check_validator(int, char *, char *);
static int string_length_check_validator(int, char *, char *);
static int yes_no_validator(int, char *, char *);
static int ip_address_validator(int, char *, char *);
static int minauth_validator(int, char *, char *);
static int password_validator(int, char *, char *);
static int signing_validator(int, char *, char *);
int propset_changed = 0;
/*
* ops vector that provides the protocol specific info and operations
* for share management.
*/
NULL, /* share */
NULL, /* unshare */
NULL, /* valid_prop */
NULL, /* valid_space */
NULL, /* security_prop */
NULL, /* legacy_opts */
NULL, /* legacy_format */
NULL, /* space_alias */
NULL, /* update_legacy */
NULL, /* delete_legacy */
NULL, /* change_notify */
NULL, /* enable_resource */
NULL, /* disable_resource */
NULL, /* get_transient_shares */
NULL, /* notify_resource */
NULL, /* rename_resource */
NULL, /* run_command */
NULL, /* command_help */
};
/*
* is_a_number(number)
*
* is the string a number in one of the forms we want to use?
*/
static int
{
int hex = 0;
number += 2;
hex = 1;
} else if (*number == '-') {
number++; /* skip the minus */
}
if (hex) {
} else {
}
}
return (ret);
}
/*
* Protocol management functions
*
* properties defined in the default files are defined in
* proto_option_defs for parsing and validation.
*/
0, 0, MAX_VALUE_BUFLEN,
0, 0, MAX_VALUE_BUFLEN,
0, 0, MAX_VALUE_BUFLEN,
0, 0, 0,
0, 0, 0,
0, 0, MAX_VALUE_BUFLEN,
0, 0, MAX_VALUE_BUFLEN,
0, 0, 60,
0, 0, MAX_VALUE_BUFLEN,
0, 0, MAX_VALUE_BUFLEN,
0, 0, MAX_VALUE_BUFLEN,
0, 0, MAX_VALUE_BUFLEN,
{NULL}
};
/*
* Check the range of value as int range.
*/
/*ARGSUSED*/
static int
{
return (SA_BAD_VALUE);
return (SA_OK);
if (!is_a_number(value)) {
ret = SA_BAD_VALUE;
} else {
int val;
ret = SA_BAD_VALUE;
}
return (ret);
}
/*
* Check the length of the string
*/
/*ARGSUSED*/
static int
{
return (SA_BAD_VALUE);
return (SA_OK);
ret = SA_BAD_VALUE;
return (ret);
}
/*
*/
/*ARGSUSED*/
static int
{
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_OK);
return (SA_BAD_VALUE);
}
/*
* Check IP address.
*/
/*ARGSUSED*/
static int
{
int len;
return (SA_BAD_VALUE);
if (len == 0)
return (SA_OK);
if (len > MAX_VALUE_BUFLEN)
return (SA_BAD_VALUE);
return (SA_OK);
}
/*ARGSUSED*/
static int
{
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_OK);
else
return (SA_BAD_VALUE);
}
/*ARGSUSED*/
static int
{
return (SA_BAD_VALUE);
return (SA_OK);
return (SA_OK);
else
return (SA_BAD_VALUE);
}
/*ARGSUSED*/
static int
{
/* mangled passwords will start with this pattern */
return (SA_OK);
return (SA_PASSWORD_ENC);
return (SA_BAD_VALUE);
return (SA_OK);
}
/*
* the protoset holds the defined options so we don't have to read
* them multiple times
*/
static int
{
int i;
return (i);
}
return (-1);
}
/*
* Load the persistent settings from SMF. Each section is an SMF
* property group with an "S-" prefix and a UUID, and the section
* is itself a property which can have a more flexible name than
* a property group name can have. The section name need not be
* the first property, so we have to be a little flexible, but
* the change of name of the property groups is a reliable way
* to know that we're seeing a different section.
*/
int
{
return (-1);
for (;;) {
prop = (scf_simple_prop_t *)
break;
/* Ignore properties that don't have our prefix */
continue;
/*
* Note property group name changes, which mark sections
*
* The memory allocated by sa_create_section is
* linked into the list of children under protoset,
* and will eventually be freed via that list.
*/
if (lastpgname)
}
/* If we get a section name, apply it and consume it */
continue;
}
/*
* We have an ordinary property. Add to the section.
*
* The memory allocated by sa_create_property is
* linked into the list of children under "sect",
* and will eventually be freed via that list.
*/
}
if (lastpgname)
return (0);
}
/*
* Save the set of properties for a particular section, which is
* stored as a single property group. Properties will have been
* changed earlier by one or more calls to smbfs_save_property(),
* which only set the value in our array and marked them as
* SMBC_MODIFIED.
*/
int
{
int i, ret = 0;
} else {
new = 1;
}
return (1);
}
SMBC_PG_INSTANCE)) != SMBC_SMF_OK) {
goto out;
}
!= SMBC_SMF_OK) {
goto out;
}
goto out;
}
continue;
else {
nonnull = 1;
}
if (ret != SMBC_SMF_OK)
goto outtrans;
}
/*
* Suppress new, null entries by not saving the section name.
*/
}
propset_changed = 0;
out:
return (ret);
}
/*
* initprotofromdefault()
*
* read the default file(s) and add the defined values to the
* protoset. Note that default values are known from the built in
* table in case the file doesn't have a definition.
*/
static int
{
return (SA_NO_MEMORY);
if (smbclnt_config_load() != 0)
return (SA_OK);
return (SA_OK);
}
/*
*
* smbfs_features()
*
* Report the plugin's features
*/
static uint64_t
{
return (SA_FEATURE_HAS_SECTIONS | SA_FEATURE_ADD_PROPERTIES);
}
/*
* smbfs_init()
*
* Initialize the smb plugin.
*/
static int
{
return (SA_SYSTEM_ERR);
}
if (initprotofromdefault() != SA_OK) {
return (SA_SYSTEM_ERR);
}
return (ret);
}
/*
* smbfs_fini()
*
* uninitialize the smb plugin. Want to avoid memory leaks.
*/
static void
{
if (propset_changed)
(void) smbfs_save_propset();
}
/*
* smbfs_get_proto_set()
*
* Return an optionset with all the protocol specific properties in
* it.
*/
static sa_protocol_properties_t
{
return (protoset);
}
/*
* smbfs_validate_proto_prop(index, name, value)
*
* Verify that the property specifed by name can take the new
* value. This is a sanity check to prevent bad values getting into
* the default files.
*/
static int
{
return (SA_BAD_VALUE);
return (SA_OK);
}
/*
* Save a property to our array; it will be stored to SMF later by
* smbfs_save_propset().
*/
int
{
char *s;
if (index == PROTO_OPT_WORKGROUP) {
}
propset_changed = 1;
if (s == NULL)
return (-1);
if (s == NULL)
return (-1);
return (0);
}
/*
* smbfs_set_proto_prop(prop)
*
* check that prop is valid.
*/
/*ARGSUSED*/
static int
{
char *name;
char *value;
char *section;
int i = -1;
return (SA_NO_SECTION);
i = findprotoopt(name);
if (i >= 0) {
if (smbfs_save_property(i, section,
value) != 0) {
ret = SA_SYSTEM_ERR;
}
}
} else
}
return (ret);
}
/*
* smbfs_get_status()
*
* What is the current status of the smbd? We use the SMF state here.
* Caller must free the returned value.
*/
static char *
{
return (smf_get_state(SMBC_DEFAULT_INSTANCE_FMRI));
}
/*
* Delete a section by its name, which we will have read into an
* XML optionset above. We need to find it and find its UUID to
* be able to generate the property group name in order to call
* smbfs_delete_property_group().
*/
static int
{
goto out;
goto out;
out:
return (ret);
}
/*
* Delete a property group by its name. Called to do a 'delsect'
* or called when smbclnt_config_load() notices an empty section
* at the end of the properties.
*/
static int
{
goto out;
SMBC_PG_INSTANCE)) != SMBC_SMF_OK)
goto out;
!= SMBC_SMF_OK)
goto out;
out:
return (ret);
}