smbrdr_logon.c revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327
/*
* 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
*/
/*
*/
#include <pthread.h>
#include <string.h>
#include <strings.h>
#include <synch.h>
#include <errno.h>
#include <smbsrv/wintypes.h>
#include <smbsrv/libsmbrdr.h>
#include <smbrdr.h>
#define SMBRDR_ANON_USER "IPC$"
static int smbrdr_session_setupx(struct sdb_logon *);
uint8_t *);
static int smbrdr_authenticate(char *, char *, uint8_t *);
/*
* If the username is SMBRDR_ANON_USER, an anonymous session will be
* established. Otherwise, an authenticated session will be established
* based on the specified credentials.
*/
int
{
int rc;
return (-1);
}
if (*pwd_hash == 0) {
"smbrdr_logon: no password");
return (-1);
}
}
"smbrdr_logon: negotiate failed");
return (-1);
}
}
/*
* Get the user session key from an already open named pipe.
* The RPC library needs this. See ndr_rpc_get_ssnkey()
*
* Returns zero (success) or an errno.
*/
int
{
struct sdb_session *session;
struct sdb_netuse *netuse;
return (EINVAL);
return (EBADF);
if (key_len > SMBAUTH_SESSION_KEY_SZ)
return (0);
}
/*
* smbrdr_authenticate
*
* This is the entry point for logging a user onto the domain. The
* session structure should have been obtained via a successful call
* to smbrdr_smb_connect. We allocate a logon structure to hold the
* user details and attempt to logon using smbrdr_session_setupx.
* Note that we expect the password fields to have been encrypted
* before this call.
*
* On success, the logon structure will be returned. Otherwise a null
* pointer will be returned.
*/
static int
{
struct sdb_session *session;
int ret;
"smbrdr_authenticate: %s: no session with %s",
return (-1);
}
/* The requested user has already been logged in */
}
}
return (-1);
}
if (smbrdr_session_setupx(logon) < 0) {
return (-1);
}
(void) smbrdr_logoffx(&old_logon);
return (ret);
}
/*
* smbrdr_session_setupx
*
* Build and send an SMB session setup command. This is used to log a
* user onto the domain. See CIFS section 4.1.2.
*
* Returns 0 on success. Otherwise returns a -ve error code.
*/
static int
{
struct sdb_session *session;
char *native_os;
char *native_lanman;
unsigned short data_bytes;
unsigned short guest;
unsigned long capabilities;
unsigned short null_size;
int rc;
/*
* Paranoia check - we should never get this
* far without a valid session structure.
*/
return (-1);
null_size = sizeof (smb_wchar_t);
} else {
null_size = sizeof (char);
}
"smbrdr_session_setupx: smbrdr_sign_init failed");
return (-1);
}
session, 0, 0);
if (status != NT_STATUS_SUCCESS) {
return (-1);
}
/*
* Regardless of the server's capabilities or what's
* reported in smb_flags2, we should report our full
* capabilities.
*/
/*
* Compute the BCC for unicode or ASCII strings.
*/
/*
* Anonymous logon: no username or domain name.
* We still need to include two null characters.
*/
13, /* smb_wct */
0xff, /* AndXCommand (none) */
SMBRDR_REQ_BUFSZ, /* MaxBufferSize */
1, /* MaxMpxCount */
0, /* VcNumber */
0, /* SessionKey */
1, /* CaseInsensitivePassLength */
0, /* CaseSensitivePassLength */
0, /* Reserved */
capabilities, /* Capabilities */
data_bytes, /* smb_bcc */
0, /* No user or domain */
} else {
13, /* smb_wct */
0xff, /* AndXCommand (none) */
SMBRDR_REQ_BUFSZ, /* MaxBufferSize */
1, /* MaxMpxCount */
0, /* Reserved */
capabilities, /* Capabilities */
data_bytes, /* smb_bcc */
}
if (rc <= 0) {
"smbrdr_session_setupx: encode failed");
return (-1);
}
if (status != NT_STATUS_SUCCESS) {
if (status == NT_STATUS_INVALID_PARAMETER) {
"If the DC is running Windows Server 2008: "
"apply hotfix KB 957441");
"If the DC is running Windows Server 2008 "
"R2: do not apply the hotfix but update "
"the registry as described in KB 957441");
}
return (-1);
}
/*
* There was a problem in decoding response from
* a Samba 2.x PDC. This server sends strings in ASCII
* format and there is one byte with value 0 between
* native_os and native_lm:
*
* FF 53 4D 42 73 00 .SMBs.
* 00 00 00 88 01 00 00 00 00 00 00 00 00 00 00 00 ................
* 00 00 00 00 BB 00 64 00 00 00 03 FF 00 00 00 01 ......d.........
* 00 1C 00 55 6E 69 78 00 53 61 6D 62 61 20 32 2E ...Unix.Samba.2.
* 32 2E 38 61 00 53 41 4D 42 41 5F 44 4F 4D 00 2.8a.SAMBA_DOM.
*
* The byte doesn't seem to be padding because when change in
* native OS from Unix to Unix1 the 0 byte is still there:
*
* FF 53 4D 42 73 00 .SMBs.
* 00 00 00 88 01 00 00 00 00 00 00 00 00 00 00 00 ................
* 00 00 00 00 BB 00 64 00 00 00 03 FF 00 00 00 00 ......d.........
* 00 1D 00 55 6E 69 78 31 00 53 61 6D 62 61 20 32 ...Unix1.Samba.2
* 2E 32 2E 38 61 00 53 41 4D 42 41 5F 44 4F 4D 00 .2.8a.SAMBA_DOM.
*/
if (rc > 0) {
else
}
if (rc <= 0) {
"smbrdr_session_setupx: decode failed");
return (-1);
}
if (guest)
return (0);
}
/*
* smbrdr_logoffx
*
* Build and send an SMB session logoff (SMB_COM_LOGOFF_ANDX) command.
* This is the inverse of an SMB_COM_SESSION_SETUP_ANDX. See CIFS
* section 4.1.3. The logon structure should have been obtained from a
* successful call to smbrdr_authenticate.
*
* Returns 0 on success. Otherwise returns a -ve error code.
*/
int
{
struct sdb_session *session;
int rc;
/* No user to logoff */
return (0);
}
return (0);
}
return (0);
}
if (status != NT_STATUS_SUCCESS) {
return (-1);
}
if (rc < 0) {
return (rc);
}
if (status != NT_STATUS_SUCCESS) {
rc = -1;
} else {
rc = 0;
}
return (rc);
}
/*
* smbrdr_logon_init
*
* Find a slot for account logon information. The account information
* is associated with a session so we need a valid session slot before
* calling this function. If we already have a record of the specified
* account, a pointer to that record is returned. Otherwise we attempt
* to allocate a new one.
*/
static struct sdb_logon *
{
int rc;
if (logon == 0)
return (0);
} else {
/* Generate (and save) the session key. */
if (rc == 0) {
}
if (rc != 0) {
return (0);
}
}
return (logon);
}