smb_pwdutil.c revision dc20a3024900c47dd2ee44b9707e6df38f7d62a5
/*
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <strings.h>
#include <synch.h>
#include <errno.h>
#include <fcntl.h>
#include <thread.h>
#include <pwd.h>
#define SMB_PASSWD "/var/smb/smbpasswd"
#define SMB_OPASSWD "/var/smb/osmbpasswd"
#define SMB_PASSTEMP "/var/smb/ptmp"
#define SMB_PASSLCK "/var/smb/.pwd.lock"
#define SMB_PWD_DISABLE "*DIS*"
#define SMB_PWD_BUFSIZE 256
#define S_WAITTIME 15
typedef enum {
SMB_PWD_NAME = 0,
} smb_pwdarg_t;
0, /* l_type */
0, /* l_whence */
0, /* l_start */
0, /* l_len */
0, /* l_sysid */
0 /* l_pid */
};
static int fildes = -1;
typedef struct smb_pwbuf {
char *pw_name;
} smb_pwbuf_t;
static int smb_pwd_lock(void);
static int smb_pwd_unlock(void);
static int smb_pwd_flck(void);
static int smb_pwd_fulck(void);
static int smb_pwd_chgpwent(smb_passwd_t *, const char *, int);
static int smb_pwd_update(const char *, const char *, int);
/*
* smb_pwd_get
*
* Returns a smb password structure for the given user name.
* smbpw is a pointer to a buffer allocated by the caller.
*
* Returns NULL upon failure.
*/
{
char buf[SMB_PWD_BUFSIZE];
int err;
err = smb_pwd_lock();
if (err != SMB_PWE_SUCCESS)
return (NULL);
(void) smb_pwd_unlock();
return (NULL);
}
break;
}
}
(void) smb_pwd_unlock();
if (!found) {
return (NULL);
}
return (smbpw);
}
/*
* smb_pwd_set
*
*/
int
{
}
/*
* smb_pwd_setcntl
*
* Change the account state. This can be making the account
*/
int
{
if (control == 0)
return (SMB_PWE_SUCCESS);
}
static int
{
int tempfd;
char buf[SMB_PWD_BUFSIZE];
int err = SMB_PWE_SUCCESS;
char uxbuf[1024];
err = smb_pwd_lock();
if (err != SMB_PWE_SUCCESS)
return (err);
goto passwd_exit;
}
goto passwd_exit;
}
goto passwd_exit;
}
(void) unlink(SMB_PASSTEMP);
goto passwd_exit;
}
lm_level = 4;
if (lm_level >= 4)
control |= SMB_PWC_NOLM;
/*
* copy old password entries to temporary file while replacing
* the entry that matches "name"
*/
if (err == SMB_PWE_USER_DISABLE)
} else {
}
if (err != SMB_PWE_SUCCESS) {
goto passwd_exit;
}
}
if (newent) {
} else {
}
if (err != SMB_PWE_SUCCESS) {
goto passwd_exit;
}
}
goto passwd_exit; /* Don't trust the temporary file */
}
/* Rename temp to passwd */
(void) unlink(SMB_PASSTEMP);
goto passwd_exit;
}
(void) unlink(SMB_PASSTEMP);
goto passwd_exit;
}
(void) unlink(SMB_PASSTEMP);
goto passwd_exit;
}
(void) smb_pwd_unlock();
return (err);
}
/*
* smb_getpwent
*
* Parse the buffer in the passed pwbuf and fill in the
* smb password structure to point to the parsed information.
* The entry format is:
*
* <user-name>:<user-id>:<LM hash>:<NTLM hash>
*
* Returns a pointer to the password structure on success,
* otherwise returns NULL.
*/
static smb_pwbuf_t *
{
char *argv[SMB_PWD_NARG];
smb_pwdarg_t i;
return (NULL);
(void) trim_whitespace(buf);
for (i = 0; i < SMB_PWD_NARG; ++i) {
return (NULL);
}
}
return (NULL);
return (pwbuf);
}
if (lm_len == SMBAUTH_HEXHASH_SZ) {
} else if (lm_len != 0) {
return (NULL);
}
if (nt_len == SMBAUTH_HEXHASH_SZ) {
} else if (nt_len != 0) {
return (NULL);
}
return (pwbuf);
}
static int
{
if (control & SMB_PWC_DISABLE) {
return (SMB_PWE_SUCCESS);
} else if ((control & SMB_PWC_ENABLE) &&
return (SMB_PWE_SUCCESS);
}
/* No password update if account is disabled */
return (SMB_PWE_USER_DISABLE);
if (control & SMB_PWC_NOLM) {
} else {
}
return (SMB_PWE_SUCCESS);
}
/*
* smb_putpwent
*
* Creates LM and NTLM hash from the given plain text password
* and write them along with user's name and Id to the smbpasswd
* file.
*/
static int
{
int rc;
} else {
}
} else {
}
if (rc <= 0)
return (SMB_PWE_WRITE_FAILED);
return (SMB_PWE_SUCCESS);
}
static int
smb_pwd_lock(void)
{
int res;
if (smb_pwd_flck()) {
switch (errno) {
case EINTR:
res = SMB_PWE_BUSY;
break;
case EACCES:
break;
case 0:
break;
}
} else
return (res);
}
static int
smb_pwd_unlock(void)
{
if (smb_pwd_fulck())
return (SMB_PWE_SYSTEM_ERROR);
return (SMB_PWE_SUCCESS);
}
static int
smb_pwd_flck(void)
{
int seconds = 0;
(void) mutex_lock(&lck_lock);
for (;;) {
/* somebody forked */
lck_pid = 0;
lck_tid = 0;
}
if (lck_tid == 0) {
break;
(void) mutex_unlock(&lck_lock);
return (0);
}
fildes = -1;
}
if (seconds++ >= S_WAITTIME) {
/*
* For compatibility with the past, pretend
* that we were interrupted by SIGALRM.
*/
break;
}
(void) mutex_unlock(&lck_lock);
(void) sleep(1);
(void) mutex_lock(&lck_lock);
}
(void) mutex_unlock(&lck_lock);
return (-1);
}
static int
smb_pwd_fulck(void)
{
(void) mutex_lock(&lck_lock);
fildes = -1;
lck_pid = 0;
lck_tid = 0;
(void) mutex_unlock(&lck_lock);
return (0);
}
(void) mutex_unlock(&lck_lock);
return (-1);
}