smb_util.c revision 1fcced4c370617db71610fecffd5451a5894ca5e
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <pthread.h>
#include <tiuser.h>
#include <netconfig.h>
#include <netdir.h>
#include <sys/systeminfo.h>
#include <libzfs.h>
#include <dlfcn.h>
#define SMB_LIB_ALT "/usr/lib/smbsrv/libsmbex.so"
extern int __multi_innetgr();
extern int __netdir_getbyaddr_nosrv(struct netconfig *,
struct nd_hostservlist **, struct netbuf *);
#define C2H(c) "0123456789ABCDEF"[(c)]
((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \
((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
'\0')
#define DEFAULT_SBOX_SIZE 256
/*
*
* hexdump
*
* Simple hex dump display function. Displays nbytes of buffer in hex and
* printable format. Non-printing characters are shown as '.'. It is safe
* to pass a null pointer. Each line begins with the offset. If nbytes is
* 0, the line will be blank except for the offset. Example output:
*
* 00000000 54 68 69 73 20 69 73 20 61 20 70 72 6F 67 72 61 This is a progra
* 00000010 6D 20 74 65 73 74 2E 00 m test..
*
*/
void
{
static char *hex = "0123456789ABCDEF";
int i, count;
int offset;
unsigned char *p;
char ascbuf[64];
char hexbuf[64];
return;
*ap = '\0';
*hp = '\0';
count = 0;
for (i = 0; i < nbytes; ++i) {
if (i && (i % 16) == 0) {
count = 0;
offset += 16;
}
(*p >= 0x20 && *p < 0x7F) ? *p : '.');
++p;
++count;
}
if (count) {
}
}
void
{
unsigned long start = 0;
}
/*
* bintohex
*
* Converts the given binary data (srcbuf) to
* its equivalent hex chars (hexbuf).
*
* hexlen should be at least twice as srclen.
* if hexbuf is not big enough returns 0.
* otherwise returns number of valid chars in
* hexbuf which is srclen * 2.
*/
{
char c;
return (0);
while (srclen-- > 0) {
c = *srcbuf++;
}
return (outlen);
}
/*
* hextobin
*
* Converts hex to binary.
*
* Assuming hexbuf only contains hex digits (chars)
* this function convert every two bytes of hexbuf
* to one byte and put it in dstbuf.
*
* hexlen should be an even number.
* dstlen should be at least half of hexlen.
*
* Returns 0 if sizes are not correct, otherwise
* returns the number of converted bytes in dstbuf
* which is half of hexlen.
*/
{
if ((hexlen % 2) != 0)
return (0);
return (0);
while (hexlen > 0) {
hexbuf++;
hexbuf++;
hexlen -= 2;
}
return (outlen);
}
/*
* Trim leading and trailing characters in the set defined by class
* from a buffer containing a null-terminated string.
* For example, if the input buffer contained "ABtext23" and class
* contains "ABC123", the buffer will contain "text" on return.
*
* This function modifies the contents of buf in place and returns
* a pointer to buf.
*/
char *
{
char *p = buf;
char *q = buf;
return (NULL);
if (p != buf) {
while ((*q = *p++) != '\0')
++q;
}
while (q != buf) {
--q;
return (buf);
*q = '\0';
}
return (buf);
}
/*
* Strip the characters in the set defined by class from a buffer
* containing a null-terminated string.
* For example, if the input buffer contained "XYA 1textZ string3"
* and class contains "123XYZ", the buffer will contain "A text string"
* on return.
*
* This function modifies the contents of buf in place and returns
* a pointer to buf.
*/
char *
{
char *p = buf;
char *q = buf;
return (NULL);
while (*p) {
*q++ = *p++;
}
*q = '\0';
return (buf);
}
/*
* trim_whitespace
*
* Trim leading and trailing whitespace chars (as defined by isspace)
* from a buffer. Example; if the input buffer contained " text ",
* it will contain "text", when we return. We assume that the buffer
* contains a null terminated string. A pointer to the buffer is
* returned.
*/
char *
trim_whitespace(char *buf)
{
char *p = buf;
char *q = buf;
return (NULL);
while (*p && isspace(*p))
++p;
while ((*q = *p++) != 0)
++q;
if (q != buf) {
while ((--q, isspace(*q)) != 0)
*q = '\0';
}
return (buf);
}
/*
* randomize
*
* Randomize the contents of the specified buffer.
*/
void
{
unsigned tmp;
unsigned i; /*LINTED E_BAD_PTR_CAST_ALIGN*/
unsigned *p = (unsigned *)data;
for (i = 0; i < dwlen; ++i)
*p++ = random();
if (remlen) {
}
}
/*
* This is the hash mechanism used to encrypt passwords for commands like
* SamrSetUserInformation. It uses a 256 byte s-box.
*/
void
unsigned char *data,
unsigned char *key,
{
unsigned char sbox[DEFAULT_SBOX_SIZE];
unsigned char tmp;
unsigned char index_i = 0;
unsigned char index_j = 0;
unsigned char j = 0;
int i;
for (i = 0; i < DEFAULT_SBOX_SIZE; ++i)
sbox[i] = (unsigned char)i;
for (i = 0; i < DEFAULT_SBOX_SIZE; ++i) {
}
for (i = 0; i < datalen; ++i) {
index_i++;
}
}
/*
* smb_chk_hostaccess
*
* Determine whether an access list grants rights to a particular host.
* We match on aliases of the hostname as well as on the canonical name.
* Names in the access list may be either hosts or netgroups; they're
* not distinguished syntactically. We check for hosts first because
* it's cheaper (just M*N strcmp()s), then try netgroups.
*
* Currently this function always returns B_TRUE for ipv6 until
* the underlying functions support ipv6
*
* Function returns:
* -1 for "all"
* 0 not found
* 1 found
*
*/
int
{
int nentries;
char *gr;
char *lasts;
char *host;
int off;
int i;
int netgroup_match;
int response;
struct nd_hostservlist *clnames;
struct sockaddr_in sa;
return (B_TRUE);
/*
* If no access list - then it's "all"
*/
return (-1);
nentries = 0;
return (1);
return (0);
}
/*
* If the list name has a '-' prepended
* then a match of the following name
* implies failure instead of success.
*/
if (*gr == '-') {
response = 0;
gr++;
} else {
response = 1;
}
/*
* The following loops through all the
* client's aliases. Usually it's just one name.
*/
/*
* If the list name begins with a dot then
* do a domain name suffix comparison.
* A single dot matches any name with no
* suffix.
*/
if (*gr == '.') {
return (response);
} else {
if (off > 0 &&
return (response);
}
}
} else {
/*
* If the list name begins with an at
* sign then do a network comparison.
*/
if (*gr == '@') {
return (response);
} else {
/*
* Just do a hostname match
*/
return (response);
}
}
}
nentries++;
}
return (netgroup_match);
}
/*
* smb_make_mask
*
* Construct a mask for an IPv4 address using the @<dotted-ip>/<len>
* syntax or use the default mask for the IP address.
*/
static uint_t
{
/*
* If the mask is specified explicitly then
* use that value, e.g.
*
* @109.104.56/28
*
* otherwise assume a mask from the zero octets
* in the least significant bits of the address, e.g.
*
* @109.104 or @109.104.0.0
*/
if (maskstr) {
: 0;
} else {
if ((addr & IN_CLASSA_HOST) == 0)
else if ((addr & IN_CLASSB_HOST) == 0)
else if ((addr & IN_CLASSC_HOST) == 0)
else
}
return (mask);
}
/*
* smb_netmatch
*
* Check to see if the address in the netbuf matches the "net"
* specified by name. The format of "name" can be:
* fully qualified domain name
* dotted IP address
* dotted IP address followed by '/<len>'
* See sharen_nfs(1M) for details.
*/
static boolean_t
{
char *mp, *p;
int i;
char buff[256];
/*
* Check if it's an IPv4 addr
*/
return (B_FALSE);
/* LINTED pointer alignment */
sizeof (struct in_addr));
if (mp)
*mp++ = '\0';
/*
* Convert a dotted IP address
* to an IP address. The conversion
* is not the same as that in inet_addr().
*/
p = name;
addr = 0;
for (i = 0; i < 4; i++) {
p = strchr(p, '.');
if (p == NULL)
break;
p++;
}
} else {
/*
* Turn the netname into
* an IP address.
*/
return (B_FALSE);
}
}
}
/*
* smb_netgroup_match
*
* Check whether any of the hostnames in clnames are
* members (or non-members) of the netgroups in glist.
* Since the innetgr lookup is rather expensive, the
* result is cached. The cached entry is valid only
* for VALID_TIME seconds. This works well because
* typically these lookups occur in clusters when
* a client is mounting.
*
* Note that this routine establishes a host membership
* in a list of netgroups - we've no idea just which
* netgroup in the list it is a member of.
*
* glist is a character array containing grc strings
* representing netgroup names (optionally prefixed
* with '-'). Each string is ended with '\0' and
* followed immediately by the next string.
*/
static boolean_t
{
char **grl;
char *gr;
char *host;
int i, j, n;
int ssize;
return (B_FALSE);
return (B_FALSE);
}
/* Check for error in syscall or NULL domain name */
if (ssize <= 1)
return (B_FALSE);
}
return (B_FALSE);
/*
* If the netgroup name has a '-' prepended
* then a match of this name implies a failure
* instead of success.
*/
/*
* Subsequent names with or without a '-' (but no mix)
* can be grouped together for a single check.
*/
break;
}
/*
* Check the netgroup for each
* of the hosts names (usually just one).
*/
1, &domain))
}
}
}
/*
* Resolve the ZFS dataset from a path.
* Returns,
* 0 = On success.
*/
int
{
char tmppath[MAXPATHLEN];
char *cp;
int rc = -1;
return (-1);
while (*cp != '\0') {
break;
break;
/*
* Ensure that there are no leading slashes
* (required for zfs_open).
*/
rc = 0;
break;
}
break;
break;
/*
* The path has multiple components.
* Remove the last component and try again.
*/
*cp = '\0';
if (tmppath[0] == '\0')
}
return (rc);
}
/*
* smb_dlopen
*
* Check to see if an interposer library exists. If it exists
* and reports a valid version number and key (UUID), return
* a handle to the library. Otherwise, return NULL.
*/
void *
smb_dlopen(void)
{
void *interposer_hdl;
typedef int (*smbex_versionfn_t)(smbex_version_t *);
return (NULL);
if (interposer_hdl == NULL)
return (NULL);
"smbex_get_version");
if ((getversion == NULL) ||
(void) dlclose(interposer_hdl);
return (NULL);
}
if ((getversion(version) != 0) ||
(void) dlclose(interposer_hdl);
return (NULL);
}
return (interposer_hdl);
}
/*
* smb_dlclose
*
* Closes handle to the interposed library.
*/
void
smb_dlclose(void *handle)
{
if (handle)
}
/*
* Returns the hostname given the IP address. Wrapper for getnameinfo.
*/
int
{
struct sockaddr_in6 sin6;
struct sockaddr_in sin;
void *sp;
salen = sizeof (struct sockaddr_in);
} else {
salen = sizeof (struct sockaddr_in6);
}
}