mirror of
https://github.com/samba-team/samba.git
synced 2025-03-26 18:50:30 +03:00
Sync 3.0 branch with head
(This used to be commit 42615b945e2e48e53a21ea47f2e45407913a6a1e)
This commit is contained in:
parent
287d49bb5d
commit
127e77e6e3
@ -282,9 +282,10 @@ static BOOL process_lockread(blocking_lock_record *blr)
|
||||
status = do_lock_spin( fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtoread,
|
||||
(SMB_BIG_UINT)startpos, READ_LOCK);
|
||||
if (NT_STATUS_V(status)) {
|
||||
if ((errno != EACCES) && (errno != EAGAIN)) {
|
||||
if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
|
||||
!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
|
||||
/*
|
||||
* We have other than a "can't get lock" POSIX
|
||||
* We have other than a "can't get lock"
|
||||
* error. Send an error.
|
||||
* Return True so we get dequeued.
|
||||
*/
|
||||
@ -348,9 +349,10 @@ static BOOL process_lock(blocking_lock_record *blr)
|
||||
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)count,
|
||||
(SMB_BIG_UINT)offset, WRITE_LOCK);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
if((errno != EACCES) && (errno != EAGAIN)) {
|
||||
if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
|
||||
!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
|
||||
/*
|
||||
* We have other than a "can't get lock" POSIX
|
||||
* We have other than a "can't get lock"
|
||||
* error. Send an error.
|
||||
* Return True so we get dequeued.
|
||||
*/
|
||||
@ -432,12 +434,13 @@ static BOOL process_lockingX(blocking_lock_record *blr)
|
||||
|
||||
reply_lockingX_success(blr);
|
||||
return True;
|
||||
} else if ((errno != EACCES) && (errno != EAGAIN)) {
|
||||
/*
|
||||
* We have other than a "can't get lock" POSIX
|
||||
* error. Free any locks we had and return an error.
|
||||
* Return True so we get dequeued.
|
||||
*/
|
||||
} else if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
|
||||
!NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
|
||||
/*
|
||||
* We have other than a "can't get lock"
|
||||
* error. Free any locks we had and return an error.
|
||||
* Return True so we get dequeued.
|
||||
*/
|
||||
|
||||
blocking_lock_reply_error(blr, status);
|
||||
return True;
|
||||
|
@ -167,17 +167,17 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass,
|
||||
|
||||
/* Make slave stdin/out/err of child. */
|
||||
|
||||
if (dup2(slave, STDIN_FILENO) != STDIN_FILENO)
|
||||
if (sys_dup2(slave, STDIN_FILENO) != STDIN_FILENO)
|
||||
{
|
||||
DEBUG(3, ("Could not re-direct stdin\n"));
|
||||
return (False);
|
||||
}
|
||||
if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO)
|
||||
if (sys_dup2(slave, STDOUT_FILENO) != STDOUT_FILENO)
|
||||
{
|
||||
DEBUG(3, ("Could not re-direct stdout\n"));
|
||||
return (False);
|
||||
}
|
||||
if (dup2(slave, STDERR_FILENO) != STDERR_FILENO)
|
||||
if (sys_dup2(slave, STDERR_FILENO) != STDERR_FILENO)
|
||||
{
|
||||
DEBUG(3, ("Could not re-direct stderr\n"));
|
||||
return (False);
|
||||
@ -196,7 +196,9 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass,
|
||||
}
|
||||
stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||||
stermios.c_lflag |= ICANON;
|
||||
#ifdef ONLCR
|
||||
stermios.c_oflag &= ~(ONLCR);
|
||||
#endif
|
||||
if (tcsetattr(0, TCSANOW, &stermios) < 0)
|
||||
{
|
||||
DEBUG(3, ("could not set attributes of pty\n"));
|
||||
|
@ -2,6 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
Manage connections_struct structures
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Copyright (C) Alexander Bokovoy 2002
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -162,11 +163,25 @@ BOOL conn_idle_all(time_t t, int deadtime)
|
||||
|
||||
void conn_free(connection_struct *conn)
|
||||
{
|
||||
smb_vfs_handle_struct *handle, *thandle;
|
||||
void (*done_fptr)(connection_struct *the_conn);
|
||||
|
||||
/* Free vfs_connection_struct */
|
||||
|
||||
if (conn->dl_handle != NULL) {
|
||||
/* Close dlopen() handle */
|
||||
sys_dlclose(conn->dl_handle);
|
||||
handle = conn->vfs_private;
|
||||
while(handle) {
|
||||
/* Close dlopen() handle */
|
||||
done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done");
|
||||
|
||||
if (done_fptr == NULL) {
|
||||
DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle));
|
||||
} else {
|
||||
done_fptr(conn);
|
||||
}
|
||||
sys_dlclose(handle->handle);
|
||||
DLIST_REMOVE(conn->vfs_private, handle);
|
||||
thandle = handle->next;
|
||||
SAFE_FREE(handle);
|
||||
handle = thandle;
|
||||
}
|
||||
|
||||
DLIST_REMOVE(Connections, conn);
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
extern fstring remote_machine;
|
||||
static TDB_CONTEXT *tdb;
|
||||
|
||||
/****************************************************************************
|
||||
@ -29,6 +28,11 @@ static TDB_CONTEXT *tdb;
|
||||
|
||||
TDB_CONTEXT *conn_tdb_ctx(void)
|
||||
{
|
||||
if (!tdb) {
|
||||
tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
|
||||
O_RDWR | O_CREAT, 0644);
|
||||
}
|
||||
|
||||
return tdb;
|
||||
}
|
||||
|
||||
@ -173,7 +177,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
|
||||
}
|
||||
crec.start = time(NULL);
|
||||
|
||||
StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
|
||||
StrnCpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1);
|
||||
StrnCpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1);
|
||||
|
||||
dbuf.dptr = (char *)&crec;
|
||||
|
@ -721,6 +721,62 @@ static BOOL user_can_read_file(connection_struct *conn, char *name)
|
||||
&access_granted, &status);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
check to see if a user can write a file (and only files, we do not
|
||||
check dirs on this one). This is only approximate,
|
||||
it is used as part of the "hide unwriteable" option. Don't
|
||||
use it for anything security sensitive
|
||||
********************************************************************/
|
||||
|
||||
static BOOL user_can_write_file(connection_struct *conn, char *name)
|
||||
{
|
||||
extern struct current_user current_user;
|
||||
SMB_STRUCT_STAT ste;
|
||||
SEC_DESC *psd = NULL;
|
||||
size_t sd_size;
|
||||
files_struct *fsp;
|
||||
int smb_action;
|
||||
int access_mode;
|
||||
NTSTATUS status;
|
||||
uint32 access_granted;
|
||||
|
||||
ZERO_STRUCT(ste);
|
||||
|
||||
/*
|
||||
* If user is a member of the Admin group
|
||||
* we never hide files from them.
|
||||
*/
|
||||
|
||||
if (conn->admin_user)
|
||||
return True;
|
||||
|
||||
/* If we can't stat it does not show it */
|
||||
if (vfs_stat(conn, name, &ste) != 0)
|
||||
return False;
|
||||
|
||||
/* Pseudo-open the file (note - no fd's created). */
|
||||
|
||||
if(S_ISDIR(ste.st_mode))
|
||||
return True;
|
||||
else
|
||||
fsp = open_file_shared1(conn, name, &ste, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
|
||||
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
|
||||
|
||||
if (!fsp)
|
||||
return False;
|
||||
|
||||
/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
|
||||
sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
|
||||
close_file(fsp, False);
|
||||
|
||||
/* No access if SD get failed. */
|
||||
if (!sd_size)
|
||||
return False;
|
||||
|
||||
return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
|
||||
&access_granted, &status);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Open a directory.
|
||||
********************************************************************/
|
||||
@ -781,6 +837,19 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Honour _hide unwriteable_ option */
|
||||
if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) {
|
||||
char *entry;
|
||||
int ret=0;
|
||||
|
||||
if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
|
||||
ret = user_can_write_file(conn, entry);
|
||||
SAFE_FREE(entry);
|
||||
}
|
||||
if (!ret)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (used + l > dirp->mallocsize) {
|
||||
int s = MAX(used+l,used+2000);
|
||||
char *r;
|
||||
|
@ -115,65 +115,67 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname)
|
||||
/****************************************************************************
|
||||
change a unix mode to a dos mode
|
||||
****************************************************************************/
|
||||
int dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
|
||||
uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
|
||||
{
|
||||
int result = 0;
|
||||
int result = 0;
|
||||
|
||||
DEBUG(8,("dos_mode: %s\n", path));
|
||||
DEBUG(8,("dos_mode: %s\n", path));
|
||||
|
||||
if ((sbuf->st_mode & S_IWUSR) == 0)
|
||||
result |= aRONLY;
|
||||
if ((sbuf->st_mode & S_IWUSR) == 0)
|
||||
result |= aRONLY;
|
||||
|
||||
if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
|
||||
result |= aARCH;
|
||||
|
||||
if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
|
||||
result |= aARCH;
|
||||
|
||||
if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
|
||||
result |= aSYSTEM;
|
||||
|
||||
if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
|
||||
result |= aHIDDEN;
|
||||
if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
|
||||
result |= aSYSTEM;
|
||||
|
||||
if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
|
||||
result |= aHIDDEN;
|
||||
|
||||
if (S_ISDIR(sbuf->st_mode))
|
||||
result = aDIR | (result & aRONLY);
|
||||
if (S_ISDIR(sbuf->st_mode))
|
||||
result = aDIR | (result & aRONLY);
|
||||
|
||||
if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)sbuf->st_blksize) {
|
||||
result |= FILE_ATTRIBUTE_SPARSE;
|
||||
}
|
||||
|
||||
#ifdef S_ISLNK
|
||||
#if LINKS_READ_ONLY
|
||||
if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
|
||||
result |= aRONLY;
|
||||
if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
|
||||
result |= aRONLY;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* hide files with a name starting with a . */
|
||||
if (lp_hide_dot_files(SNUM(conn)))
|
||||
{
|
||||
char *p = strrchr_m(path,'/');
|
||||
if (p)
|
||||
p++;
|
||||
else
|
||||
p = path;
|
||||
|
||||
if (p[0] == '.' && p[1] != '.' && p[1] != 0)
|
||||
result |= aHIDDEN;
|
||||
}
|
||||
/* hide files with a name starting with a . */
|
||||
if (lp_hide_dot_files(SNUM(conn))) {
|
||||
char *p = strrchr_m(path,'/');
|
||||
if (p)
|
||||
p++;
|
||||
else
|
||||
p = path;
|
||||
|
||||
if (p[0] == '.' && p[1] != '.' && p[1] != 0)
|
||||
result |= aHIDDEN;
|
||||
}
|
||||
|
||||
/* Optimization : Only call is_hidden_path if it's not already
|
||||
hidden. */
|
||||
if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
|
||||
result |= aHIDDEN;
|
||||
}
|
||||
|
||||
/* Optimization : Only call is_hidden_path if it's not already
|
||||
hidden. */
|
||||
if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path))
|
||||
{
|
||||
result |= aHIDDEN;
|
||||
}
|
||||
DEBUG(8,("dos_mode returning "));
|
||||
|
||||
DEBUG(8,("dos_mode returning "));
|
||||
if (result & aHIDDEN) DEBUG(8, ("h"));
|
||||
if (result & aRONLY ) DEBUG(8, ("r"));
|
||||
if (result & aSYSTEM) DEBUG(8, ("s"));
|
||||
if (result & aDIR ) DEBUG(8, ("d"));
|
||||
if (result & aARCH ) DEBUG(8, ("a"));
|
||||
|
||||
DEBUG(8,("\n"));
|
||||
|
||||
if (result & aHIDDEN) DEBUG(8, ("h"));
|
||||
if (result & aRONLY ) DEBUG(8, ("r"));
|
||||
if (result & aSYSTEM) DEBUG(8, ("s"));
|
||||
if (result & aDIR ) DEBUG(8, ("d"));
|
||||
if (result & aARCH ) DEBUG(8, ("a"));
|
||||
|
||||
DEBUG(8,("\n"));
|
||||
|
||||
return(result);
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -163,7 +163,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
|
||||
int write_path = -1;
|
||||
|
||||
if (fsp->print_file)
|
||||
return print_job_write(fsp->print_jobid, data, n);
|
||||
return print_job_write(SNUM(fsp->conn), fsp->print_jobid, data, n);
|
||||
|
||||
if (!fsp->can_write) {
|
||||
errno = EPERM;
|
||||
|
@ -29,7 +29,6 @@
|
||||
extern BOOL case_sensitive;
|
||||
extern BOOL case_preserve;
|
||||
extern BOOL short_case_preserve;
|
||||
extern fstring remote_machine;
|
||||
extern BOOL use_mangled_map;
|
||||
|
||||
static BOOL scan_directory(char *path, char *name,connection_struct *conn,BOOL docache);
|
||||
|
@ -443,7 +443,7 @@ static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
|
||||
/* the client expects localtime */
|
||||
t -= TimeDiff(t);
|
||||
|
||||
PACKI(desc,"W",queue->job); /* uJobId */
|
||||
PACKI(desc,"W",pjobid_to_rap(snum,queue->job)); /* uJobId */
|
||||
if (uLevel == 1) {
|
||||
PACKS(desc,"B21",queue->fs_user); /* szUserName */
|
||||
PACKS(desc,"B",""); /* pad */
|
||||
@ -933,7 +933,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
|
||||
if (!mdrcnt && lp_disable_spoolss())
|
||||
desc.errcode = ERRbuftoosmall;
|
||||
|
||||
*rdata_len = desc.usedlen;
|
||||
*rdata_len = desc.usedlen;
|
||||
*rparam_len = 6;
|
||||
*rparam = REALLOC(*rparam,*rparam_len);
|
||||
SSVALS(*rparam,0,desc.errcode);
|
||||
@ -2181,11 +2181,14 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
|
||||
char *str1 = param+2;
|
||||
char *str2 = skip_string(str1,1);
|
||||
char *p = skip_string(str2,1);
|
||||
int jobid, errcode;
|
||||
uint32 jobid;
|
||||
int snum;
|
||||
int errcode;
|
||||
extern struct current_user current_user;
|
||||
WERROR werr = WERR_OK;
|
||||
|
||||
jobid = SVAL(p,0);
|
||||
if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
|
||||
return False;
|
||||
|
||||
/* check it's a supported varient */
|
||||
if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
|
||||
@ -2195,7 +2198,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
|
||||
*rparam = REALLOC(*rparam,*rparam_len);
|
||||
*rdata_len = 0;
|
||||
|
||||
if (!print_job_exists(jobid)) {
|
||||
if (!print_job_exists(snum, jobid)) {
|
||||
errcode = NERR_JobNotFound;
|
||||
goto out;
|
||||
}
|
||||
@ -2204,15 +2207,15 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
|
||||
|
||||
switch (function) {
|
||||
case 81: /* delete */
|
||||
if (print_job_delete(¤t_user, jobid, &werr))
|
||||
if (print_job_delete(¤t_user, snum, jobid, &werr))
|
||||
errcode = NERR_Success;
|
||||
break;
|
||||
case 82: /* pause */
|
||||
if (print_job_pause(¤t_user, jobid, &werr))
|
||||
if (print_job_pause(¤t_user, snum, jobid, &werr))
|
||||
errcode = NERR_Success;
|
||||
break;
|
||||
case 83: /* resume */
|
||||
if (print_job_resume(¤t_user, jobid, &werr))
|
||||
if (print_job_resume(¤t_user, snum, jobid, &werr))
|
||||
errcode = NERR_Success;
|
||||
break;
|
||||
}
|
||||
@ -2313,12 +2316,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
|
||||
char *str1 = param+2;
|
||||
char *str2 = skip_string(str1,1);
|
||||
char *p = skip_string(str2,1);
|
||||
int jobid;
|
||||
uint32 jobid;
|
||||
int snum;
|
||||
int uLevel = SVAL(p,2);
|
||||
int function = SVAL(p,4);
|
||||
int place, errcode;
|
||||
|
||||
jobid = SVAL(p,0);
|
||||
if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
|
||||
return False;
|
||||
*rparam_len = 4;
|
||||
*rparam = REALLOC(*rparam,*rparam_len);
|
||||
|
||||
@ -2329,7 +2334,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
|
||||
(!check_printjob_info(&desc,uLevel,str2)))
|
||||
return(False);
|
||||
|
||||
if (!print_job_exists(jobid)) {
|
||||
if (!print_job_exists(snum, jobid)) {
|
||||
errcode=NERR_JobNotFound;
|
||||
goto out;
|
||||
}
|
||||
@ -2341,14 +2346,14 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
|
||||
/* change job place in the queue,
|
||||
data gives the new place */
|
||||
place = SVAL(data,0);
|
||||
if (print_job_set_place(jobid, place)) {
|
||||
if (print_job_set_place(snum, jobid, place)) {
|
||||
errcode=NERR_Success;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xb:
|
||||
/* change print job name, data gives the name */
|
||||
if (print_job_set_name(jobid, data)) {
|
||||
if (print_job_set_name(snum, jobid, data)) {
|
||||
errcode=NERR_Success;
|
||||
}
|
||||
break;
|
||||
@ -2994,7 +2999,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
|
||||
int count;
|
||||
int i;
|
||||
int snum;
|
||||
int job;
|
||||
uint32 jobid;
|
||||
struct pack_desc desc;
|
||||
print_queue_struct *queue=NULL;
|
||||
print_status_struct status;
|
||||
@ -3011,14 +3016,14 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
|
||||
if (strcmp(str1,"WWrLh") != 0) return False;
|
||||
if (!check_printjob_info(&desc,uLevel,str2)) return False;
|
||||
|
||||
job = SVAL(p,0);
|
||||
snum = print_job_snum(job);
|
||||
if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
|
||||
return False;
|
||||
|
||||
if (snum < 0 || !VALID_SNUM(snum)) return(False);
|
||||
|
||||
count = print_queue_status(snum,&queue,&status);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (queue[i].job == job) break;
|
||||
if (queue[i].job == jobid) break;
|
||||
}
|
||||
|
||||
if (mdrcnt > 0) {
|
||||
@ -3549,7 +3554,7 @@ static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,cha
|
||||
|
||||
|
||||
|
||||
struct
|
||||
const static struct
|
||||
{
|
||||
char *name;
|
||||
int id;
|
||||
|
@ -202,13 +202,13 @@ static BOOL is_mangled_component(const char *name)
|
||||
|
||||
M_DEBUG(0,("is_mangled_component %s ?\n", name));
|
||||
|
||||
/* the best distinguishing characteristic is the ~ */
|
||||
if (name[6] != '~') return False;
|
||||
|
||||
/* check the length */
|
||||
len = strlen(name);
|
||||
if (len > 12 || len < 8) return False;
|
||||
|
||||
/* the best distinguishing characteristic is the ~ */
|
||||
if (name[6] != '~') return False;
|
||||
|
||||
/* check extension */
|
||||
if (len > 8) {
|
||||
if (name[8] != '.') return False;
|
||||
|
@ -23,7 +23,6 @@
|
||||
extern int Protocol;
|
||||
extern int max_recv;
|
||||
extern fstring global_myworkgroup;
|
||||
extern fstring remote_machine;
|
||||
BOOL global_encrypted_passwords_negotiated = False;
|
||||
BOOL global_spnego_negotiated = False;
|
||||
struct auth_context *negprot_global_auth_context = NULL;
|
||||
@ -200,14 +199,11 @@ static int negprot_spnego(char *p)
|
||||
if (lp_security() != SEC_ADS) {
|
||||
blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
|
||||
} else {
|
||||
ADS_STRUCT *ads;
|
||||
ads = ads_init_simple();
|
||||
/* win2000 uses host$@REALM, which we will probably use eventually,
|
||||
but for now this works */
|
||||
asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
|
||||
asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
|
||||
blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
|
||||
free(principal);
|
||||
ads_destroy(&ads);
|
||||
}
|
||||
memcpy(p, blob.data, blob.length);
|
||||
len = blob.length;
|
||||
@ -288,10 +284,12 @@ static int reply_nt1(char *inbuf, char *outbuf)
|
||||
if (!negotiate_spnego) {
|
||||
/* Create a token value and add it to the outgoing packet. */
|
||||
if (global_encrypted_passwords_negotiated) {
|
||||
/* note that we do not send a challenge at all if
|
||||
we are using plaintext */
|
||||
get_challenge(p);
|
||||
SSVALS(outbuf,smb_vwv16+1,8);
|
||||
p += 8;
|
||||
}
|
||||
SSVALS(outbuf,smb_vwv16+1,8);
|
||||
p += 8;
|
||||
p += srvstr_push(outbuf, p, global_myworkgroup, -1,
|
||||
STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
|
||||
DEBUG(3,("not using SPNEGO\n"));
|
||||
@ -412,8 +410,17 @@ int reply_negprot(connection_struct *conn,
|
||||
char *p;
|
||||
int bcc = SVAL(smb_buf(inbuf),-2);
|
||||
int arch = ARCH_ALL;
|
||||
|
||||
static BOOL done_negprot = False;
|
||||
|
||||
START_PROFILE(SMBnegprot);
|
||||
|
||||
if (done_negprot) {
|
||||
END_PROFILE(SMBnegprot);
|
||||
exit_server("multiple negprot's are not permitted");
|
||||
}
|
||||
done_negprot = True;
|
||||
|
||||
p = smb_buf(inbuf)+1;
|
||||
while (p < (smb_buf(inbuf) + bcc)) {
|
||||
Index++;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -89,29 +89,6 @@ void invalidate_all_vuids(void)
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
return a validated username
|
||||
****************************************************************************/
|
||||
char *validated_username(uint16 vuid)
|
||||
{
|
||||
user_struct *vuser = get_valid_user_struct(vuid);
|
||||
if (vuser == NULL)
|
||||
return 0;
|
||||
return(vuser->user.unix_name);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
return a validated domain
|
||||
****************************************************************************/
|
||||
char *validated_domain(uint16 vuid)
|
||||
{
|
||||
user_struct *vuser = get_valid_user_struct(vuid);
|
||||
if (vuser == NULL)
|
||||
return 0;
|
||||
return(vuser->user.domain);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create the SID list for this user.
|
||||
****************************************************************************/
|
||||
@ -207,7 +184,7 @@ has been given. vuid is biased by an offset. This allows us to
|
||||
tell random client vuid's (normally zero) from valid vuids.
|
||||
****************************************************************************/
|
||||
|
||||
int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
|
||||
int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
|
||||
{
|
||||
user_struct *vuser = NULL;
|
||||
uid_t uid;
|
||||
@ -297,7 +274,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
|
||||
/* Create an NT_USER_TOKEN struct for this user. */
|
||||
vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, vuser->guest, server_info->ptok);
|
||||
|
||||
DEBUG(3,("uid %d registered to name %s\n",(int)vuser->uid,vuser->user.unix_name));
|
||||
DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
|
||||
|
||||
next_vuid++;
|
||||
num_validated_vuids++;
|
||||
@ -311,8 +288,9 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
|
||||
}
|
||||
|
||||
/* Register a home dir service for this user */
|
||||
if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)
|
||||
&& (lp_servicenumber(vuser->user.unix_name) < 0)) {
|
||||
if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) {
|
||||
DEBUG(3, ("Adding/updating homes service for user '%s' using home direcotry: '%s'\n",
|
||||
vuser->user.unix_name, vuser->unix_homedir));
|
||||
vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir);
|
||||
} else {
|
||||
vuser->homes_snum = -1;
|
||||
@ -325,7 +303,7 @@ int register_vuid(auth_serversupplied_info *server_info, char *smb_name)
|
||||
/****************************************************************************
|
||||
add a name to the session users list
|
||||
****************************************************************************/
|
||||
void add_session_user(char *user)
|
||||
void add_session_user(const char *user)
|
||||
{
|
||||
fstring suser;
|
||||
StrnCpy(suser,user,sizeof(suser)-1);
|
||||
@ -373,7 +351,7 @@ BOOL user_ok(const char *user,int snum)
|
||||
if (valid) str_list_free (&valid);
|
||||
|
||||
if (ret && lp_onlyuser(snum)) {
|
||||
char **user_list = str_list_make (lp_username(snum));
|
||||
char **user_list = str_list_make (lp_username(snum), NULL);
|
||||
if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) {
|
||||
ret = user_in_list(user, user_list);
|
||||
}
|
||||
|
@ -2296,7 +2296,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo
|
||||
switch(tagtype) {
|
||||
case SMB_ACL_USER_OBJ:
|
||||
perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR);
|
||||
break;
|
||||
break;
|
||||
case SMB_ACL_GROUP_OBJ:
|
||||
perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP);
|
||||
break;
|
||||
|
@ -152,7 +152,7 @@ static void async_processing(char *buffer, int buffer_len)
|
||||
Returns False on timeout or error.
|
||||
Else returns True.
|
||||
|
||||
The timeout is in milli seconds
|
||||
The timeout is in milliseconds
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
|
||||
@ -341,9 +341,9 @@ force write permissions on print services.
|
||||
functions. Any message that has a NULL function is unimplemented -
|
||||
please feel free to contribute implementations!
|
||||
*/
|
||||
static struct smb_message_struct
|
||||
const static struct smb_message_struct
|
||||
{
|
||||
char *name;
|
||||
const char *name;
|
||||
int (*fn)(connection_struct *conn, char *, char *, int, int);
|
||||
int flags;
|
||||
}
|
||||
@ -386,7 +386,7 @@ static struct smb_message_struct
|
||||
/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
|
||||
/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
|
||||
/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
|
||||
/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
|
||||
/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
|
||||
/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
|
||||
/* 0x27 */ { "SMBioctl",reply_ioctl,0},
|
||||
/* 0x28 */ { "SMBioctls",NULL,AS_USER},
|
||||
@ -399,7 +399,7 @@ static struct smb_message_struct
|
||||
/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
|
||||
/* 0x30 */ { NULL, NULL, 0 },
|
||||
/* 0x31 */ { NULL, NULL, 0 },
|
||||
/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
|
||||
/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
|
||||
/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
|
||||
/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
|
||||
/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
|
||||
@ -611,7 +611,7 @@ static struct smb_message_struct
|
||||
/*******************************************************************
|
||||
dump a prs to a file
|
||||
********************************************************************/
|
||||
static void smb_dump(char *name, int type, char *data, ssize_t len)
|
||||
static void smb_dump(const char *name, int type, char *data, ssize_t len)
|
||||
{
|
||||
int fd, i;
|
||||
pstring fname;
|
||||
@ -896,7 +896,7 @@ void process_smb(char *inbuf, char *outbuf)
|
||||
/****************************************************************************
|
||||
return a string containing the function name of a SMB command
|
||||
****************************************************************************/
|
||||
char *smb_fn_name(int type)
|
||||
const char *smb_fn_name(int type)
|
||||
{
|
||||
static char *unknown_name = "SMBunknown";
|
||||
|
||||
@ -1228,13 +1228,6 @@ void smbd_process(void)
|
||||
|
||||
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
|
||||
|
||||
/* re-initialise the timezone */
|
||||
TimeInit();
|
||||
|
||||
/* register our message handlers */
|
||||
message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
|
||||
talloc_init_named("dummy!");
|
||||
|
||||
while (True) {
|
||||
int deadtime = lp_deadtime()*60;
|
||||
int select_timeout = setup_select_timeout();
|
||||
|
@ -38,7 +38,6 @@ extern pstring global_myname;
|
||||
extern int global_oplock_break;
|
||||
unsigned int smb_echo_count = 0;
|
||||
|
||||
extern fstring remote_machine;
|
||||
extern BOOL global_encrypted_passwords_negotiated;
|
||||
|
||||
|
||||
@ -53,10 +52,11 @@ int reply_special(char *inbuf,char *outbuf)
|
||||
int msg_flags = CVAL(inbuf,1);
|
||||
pstring name1,name2;
|
||||
|
||||
extern fstring local_machine;
|
||||
int len;
|
||||
char name_type = 0;
|
||||
|
||||
static BOOL already_got_session = False;
|
||||
|
||||
*name1 = *name2 = 0;
|
||||
|
||||
memset(outbuf,'\0',smb_size);
|
||||
@ -65,6 +65,11 @@ int reply_special(char *inbuf,char *outbuf)
|
||||
|
||||
switch (msg_type) {
|
||||
case 0x81: /* session request */
|
||||
|
||||
if (already_got_session) {
|
||||
exit_server("multiple session request not permitted");
|
||||
}
|
||||
|
||||
SCVAL(outbuf,0,0x82);
|
||||
SCVAL(outbuf,3,0);
|
||||
if (name_len(inbuf+4) > 50 ||
|
||||
@ -77,24 +82,19 @@ int reply_special(char *inbuf,char *outbuf)
|
||||
DEBUG(2,("netbios connect: name1=%s name2=%s\n",
|
||||
name1,name2));
|
||||
|
||||
fstrcpy(remote_machine,name2);
|
||||
remote_machine[15] = 0;
|
||||
trim_string(remote_machine," "," ");
|
||||
strlower(remote_machine);
|
||||
alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
|
||||
name1[15] = 0;
|
||||
|
||||
fstrcpy(local_machine,name1);
|
||||
len = strlen(local_machine);
|
||||
len = strlen(name2);
|
||||
if (len == 16) {
|
||||
name_type = local_machine[15];
|
||||
local_machine[15] = 0;
|
||||
name_type = name2[15];
|
||||
name2[15] = 0;
|
||||
}
|
||||
trim_string(local_machine," "," ");
|
||||
strlower(local_machine);
|
||||
alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
|
||||
|
||||
set_local_machine_name(name1);
|
||||
set_remote_machine_name(name2);
|
||||
|
||||
DEBUG(2,("netbios connect: local=%s remote=%s\n",
|
||||
local_machine, remote_machine ));
|
||||
get_local_machine_name(), get_remote_machine_name() ));
|
||||
|
||||
if (name_type == 'R') {
|
||||
/* We are being asked for a pathworks session ---
|
||||
@ -107,7 +107,7 @@ int reply_special(char *inbuf,char *outbuf)
|
||||
of possibly valid usernames if we are operating
|
||||
in share mode security */
|
||||
if (lp_security() == SEC_SHARE) {
|
||||
add_session_user(remote_machine);
|
||||
add_session_user(get_remote_machine_name());
|
||||
}
|
||||
|
||||
reload_services(True);
|
||||
@ -115,6 +115,7 @@ int reply_special(char *inbuf,char *outbuf)
|
||||
|
||||
claim_connection(NULL,"",MAXSTATUS,True);
|
||||
|
||||
already_got_session = True;
|
||||
break;
|
||||
|
||||
case 0x89: /* session keepalive request
|
||||
@ -148,7 +149,8 @@ int reply_special(char *inbuf,char *outbuf)
|
||||
int reply_tcon(connection_struct *conn,
|
||||
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
|
||||
{
|
||||
pstring service;
|
||||
const char *service;
|
||||
pstring service_buf;
|
||||
pstring password;
|
||||
pstring dev;
|
||||
int outsize = 0;
|
||||
@ -160,17 +162,19 @@ int reply_tcon(connection_struct *conn,
|
||||
|
||||
START_PROFILE(SMBtcon);
|
||||
|
||||
*service = *password = *dev = 0;
|
||||
*service_buf = *password = *dev = 0;
|
||||
|
||||
p = smb_buf(inbuf)+1;
|
||||
p += srvstr_pull_buf(inbuf, service, p, sizeof(service), STR_TERMINATE) + 1;
|
||||
p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
|
||||
pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
|
||||
p += pwlen;
|
||||
p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
|
||||
|
||||
p = strrchr_m(service,'\\');
|
||||
p = strrchr_m(service_buf,'\\');
|
||||
if (p) {
|
||||
pstrcpy(service, p+1);
|
||||
service = p+1;
|
||||
} else {
|
||||
service = service_buf;
|
||||
}
|
||||
|
||||
password_blob = data_blob(password, pwlen+1);
|
||||
@ -354,10 +358,13 @@ int reply_ioctl(connection_struct *conn,
|
||||
switch (ioctl_code)
|
||||
{
|
||||
case IOCTL_QUERY_JOB_INFO:
|
||||
SSVAL(p,0,fsp->print_jobid); /* Job number */
|
||||
{
|
||||
uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
|
||||
SSVAL(p,0,rap_jobid); /* Job number */
|
||||
srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
|
||||
srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
END_PROFILE(SMBioctl);
|
||||
@ -2744,6 +2751,8 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
||||
|
||||
srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
|
||||
|
||||
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
|
||||
|
||||
status = mkdir_internal(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
return ERROR_NT(status);
|
||||
|
@ -38,8 +38,6 @@ extern pstring user_socket_options;
|
||||
extern int dcelogin_atmost_once;
|
||||
#endif /* WITH_DFS */
|
||||
|
||||
extern fstring remote_machine;
|
||||
|
||||
/* really we should have a top level context structure that has the
|
||||
client file descriptor as an element. That would require a major rewrite :(
|
||||
|
||||
@ -133,7 +131,7 @@ static BOOL open_sockets_inetd(void)
|
||||
smbd_set_server_fd(dup(0));
|
||||
|
||||
/* close our standard file descriptors */
|
||||
close_low_fds();
|
||||
close_low_fds(False); /* Don't close stderr */
|
||||
|
||||
set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
|
||||
set_socket_options(smbd_server_fd(), user_socket_options);
|
||||
@ -151,13 +149,15 @@ static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len)
|
||||
Open the socket communication.
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL open_sockets(BOOL is_daemon,int port)
|
||||
static BOOL open_sockets_smbd(BOOL is_daemon,const char *smb_ports)
|
||||
{
|
||||
int num_interfaces = iface_count();
|
||||
int num_sockets = 0;
|
||||
int fd_listenset[FD_SETSIZE];
|
||||
fd_set listen_set;
|
||||
int s;
|
||||
int i;
|
||||
char *ports;
|
||||
|
||||
if (!is_daemon) {
|
||||
return open_sockets_inetd();
|
||||
@ -176,73 +176,106 @@ static BOOL open_sockets(BOOL is_daemon,int port)
|
||||
|
||||
/* Stop zombies */
|
||||
CatchChild();
|
||||
|
||||
|
||||
|
||||
FD_ZERO(&listen_set);
|
||||
|
||||
if(lp_interfaces() && lp_bind_interfaces_only()) {
|
||||
/* use a reasonable default set of ports - listing on 445 and 139 */
|
||||
if (!smb_ports) {
|
||||
ports = lp_smb_ports();
|
||||
if (!ports || !*ports) {
|
||||
ports = SMB_PORTS;
|
||||
}
|
||||
ports = strdup(ports);
|
||||
} else {
|
||||
ports = strdup(smb_ports);
|
||||
}
|
||||
|
||||
if (lp_interfaces() && lp_bind_interfaces_only()) {
|
||||
/* We have been given an interfaces line, and been
|
||||
told to only bind to those interfaces. Create a
|
||||
socket per interface and bind to only these.
|
||||
*/
|
||||
|
||||
if(num_interfaces > FD_SETSIZE) {
|
||||
DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \
|
||||
max can be %d\n",
|
||||
num_interfaces, FD_SETSIZE));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Now open a listen socket for each of the
|
||||
interfaces. */
|
||||
for(i = 0; i < num_interfaces; i++) {
|
||||
struct in_addr *ifip = iface_n_ip(i);
|
||||
|
||||
fstring tok;
|
||||
char *ptr;
|
||||
|
||||
if(ifip == NULL) {
|
||||
DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i));
|
||||
DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i));
|
||||
continue;
|
||||
}
|
||||
s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
|
||||
if(s == -1)
|
||||
return False;
|
||||
|
||||
/* ready to listen */
|
||||
set_socket_options(s,"SO_KEEPALIVE");
|
||||
set_socket_options(s,user_socket_options);
|
||||
for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) {
|
||||
unsigned port = atoi(tok);
|
||||
if (port == 0) continue;
|
||||
s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
|
||||
if(s == -1)
|
||||
return False;
|
||||
|
||||
/* ready to listen */
|
||||
set_socket_options(s,"SO_KEEPALIVE");
|
||||
set_socket_options(s,user_socket_options);
|
||||
|
||||
if (listen(s, 5) == -1) {
|
||||
DEBUG(0,("listen: %s\n",strerror(errno)));
|
||||
close(s);
|
||||
return False;
|
||||
if (listen(s, 5) == -1) {
|
||||
DEBUG(0,("listen: %s\n",strerror(errno)));
|
||||
close(s);
|
||||
return False;
|
||||
}
|
||||
FD_SET(s,&listen_set);
|
||||
|
||||
num_sockets++;
|
||||
if (num_sockets >= FD_SETSIZE) {
|
||||
DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
FD_SET(s,&listen_set);
|
||||
}
|
||||
} else {
|
||||
/* Just bind to 0.0.0.0 - accept connections
|
||||
from anywhere. */
|
||||
|
||||
fstring tok;
|
||||
char *ptr;
|
||||
|
||||
num_interfaces = 1;
|
||||
|
||||
/* open an incoming socket */
|
||||
s = open_socket_in(SOCK_STREAM, port, 0,
|
||||
interpret_addr(lp_socket_address()),True);
|
||||
if (s == -1)
|
||||
return(False);
|
||||
for (ptr=ports; next_token(&ptr, tok, NULL, sizeof(tok)); ) {
|
||||
unsigned port = atoi(tok);
|
||||
if (port == 0) continue;
|
||||
/* open an incoming socket */
|
||||
s = open_socket_in(SOCK_STREAM, port, 0,
|
||||
interpret_addr(lp_socket_address()),True);
|
||||
if (s == -1)
|
||||
return(False);
|
||||
|
||||
/* ready to listen */
|
||||
set_socket_options(s,"SO_KEEPALIVE");
|
||||
set_socket_options(s,user_socket_options);
|
||||
/* ready to listen */
|
||||
set_socket_options(s,"SO_KEEPALIVE");
|
||||
set_socket_options(s,user_socket_options);
|
||||
|
||||
if (listen(s, 5) == -1) {
|
||||
DEBUG(0,("open_sockets_smbd: listen: %s\n",
|
||||
strerror(errno)));
|
||||
close(s);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (listen(s, 5) == -1) {
|
||||
DEBUG(0,("open_sockets: listen: %s\n",
|
||||
strerror(errno)));
|
||||
close(s);
|
||||
return False;
|
||||
fd_listenset[num_sockets] = s;
|
||||
FD_SET(s,&listen_set);
|
||||
|
||||
num_sockets++;
|
||||
|
||||
if (num_sockets >= FD_SETSIZE) {
|
||||
DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n"));
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
fd_listenset[0] = s;
|
||||
FD_SET(s,&listen_set);
|
||||
}
|
||||
|
||||
SAFE_FREE(ports);
|
||||
|
||||
/* Listen to messages */
|
||||
|
||||
message_register(MSG_SMB_SAM_SYNC, msg_sam_sync);
|
||||
@ -293,7 +326,7 @@ max can be %d\n",
|
||||
socklen_t in_addrlen = sizeof(addr);
|
||||
|
||||
s = -1;
|
||||
for(i = 0; i < num_interfaces; i++) {
|
||||
for(i = 0; i < num_sockets; i++) {
|
||||
if(FD_ISSET(fd_listenset[i],&lfds)) {
|
||||
s = fd_listenset[i];
|
||||
/* Clear this so we don't look
|
||||
@ -309,7 +342,7 @@ max can be %d\n",
|
||||
continue;
|
||||
|
||||
if (smbd_server_fd() == -1) {
|
||||
DEBUG(0,("open_sockets: accept: %s\n",
|
||||
DEBUG(0,("open_sockets_smbd: accept: %s\n",
|
||||
strerror(errno)));
|
||||
continue;
|
||||
}
|
||||
@ -318,17 +351,21 @@ max can be %d\n",
|
||||
/* Child code ... */
|
||||
|
||||
/* close the listening socket(s) */
|
||||
for(i = 0; i < num_interfaces; i++)
|
||||
for(i = 0; i < num_sockets; i++)
|
||||
close(fd_listenset[i]);
|
||||
|
||||
/* close our standard file
|
||||
descriptors */
|
||||
close_low_fds();
|
||||
close_low_fds(False);
|
||||
am_parent = 0;
|
||||
|
||||
set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
|
||||
set_socket_options(smbd_server_fd(),user_socket_options);
|
||||
|
||||
/* this is needed so that we get decent entries
|
||||
in smbstatus for port 445 connects */
|
||||
set_remote_machine_name(get_socket_addr(smbd_server_fd()));
|
||||
|
||||
/* Reset global variables in util.c so
|
||||
that client substitutions will be
|
||||
done correctly in the process. */
|
||||
@ -382,8 +419,6 @@ BOOL reload_services(BOOL test)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
set_register_printer_fn();
|
||||
|
||||
if (lp_loaded()) {
|
||||
pstring fname;
|
||||
pstrcpy(fname,lp_configfile());
|
||||
@ -611,7 +646,7 @@ static void usage(char *pname)
|
||||
BOOL is_daemon = False;
|
||||
BOOL interactive = False;
|
||||
BOOL specified_logfile = False;
|
||||
int port = SMB_PORT;
|
||||
char *ports = NULL;
|
||||
int opt;
|
||||
pstring logfile;
|
||||
|
||||
@ -666,7 +701,7 @@ static void usage(char *pname)
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
ports = optarg;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
@ -705,7 +740,7 @@ static void usage(char *pname)
|
||||
lp_set_logfile(logfile);
|
||||
}
|
||||
|
||||
fstrcpy(remote_machine, "smbd");
|
||||
set_remote_machine_name("smbd");
|
||||
|
||||
setup_logging(argv[0],interactive);
|
||||
|
||||
@ -773,11 +808,6 @@ static void usage(char *pname)
|
||||
|
||||
init_structs();
|
||||
|
||||
/* don't call winbind for our domain if we are the DC */
|
||||
if (lp_domain_logons()) {
|
||||
winbind_exclude_domain(lp_workgroup());
|
||||
}
|
||||
|
||||
#ifdef WITH_PROFILE
|
||||
if (!profile_setup(False)) {
|
||||
DEBUG(0,("ERROR: failed to setup profiling\n"));
|
||||
@ -839,13 +869,15 @@ static void usage(char *pname)
|
||||
start_background_queue();
|
||||
*/
|
||||
|
||||
if (!open_sockets(is_daemon,port))
|
||||
if (!open_sockets_smbd(is_daemon,ports))
|
||||
exit(1);
|
||||
|
||||
/*
|
||||
* everything after this point is run after the fork()
|
||||
*/
|
||||
|
||||
namecache_enable();
|
||||
|
||||
if (!locking_init(0))
|
||||
exit(1);
|
||||
|
||||
@ -889,6 +921,13 @@ static void usage(char *pname)
|
||||
if (!init_change_notify())
|
||||
exit(1);
|
||||
|
||||
/* re-initialise the timezone */
|
||||
TimeInit();
|
||||
|
||||
/* register our message handlers */
|
||||
message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
|
||||
talloc_init_named("dummy!");
|
||||
|
||||
smbd_process();
|
||||
|
||||
uni_group_cache_shutdown();
|
||||
|
@ -27,9 +27,7 @@ extern BOOL short_case_preserve;
|
||||
extern BOOL case_mangle;
|
||||
extern BOOL case_sensitive;
|
||||
extern BOOL use_mangled_map;
|
||||
extern fstring remote_machine;
|
||||
extern userdom_struct current_user_info;
|
||||
extern fstring remote_machine;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
@ -104,7 +102,9 @@ int add_home_service(const char *service, const char *username, const char *home
|
||||
}
|
||||
}
|
||||
|
||||
lp_add_home(service, iHomeService, username, homedir);
|
||||
if (!lp_add_home(service, iHomeService, username, homedir)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return lp_servicenumber(service);
|
||||
|
||||
@ -347,7 +347,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
|
||||
}
|
||||
|
||||
if (lp_guest_only(snum)) {
|
||||
char *guestname = lp_guestaccount();
|
||||
const char *guestname = lp_guestaccount();
|
||||
guest = True;
|
||||
force = True;
|
||||
pass = getpwnam_alloc(guestname);
|
||||
@ -521,7 +521,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
|
||||
pstrcpy(s,lp_pathname(snum));
|
||||
standard_sub_conn(conn,s,sizeof(s));
|
||||
string_set(&conn->connectpath,s);
|
||||
DEBUG(3,("Connect path is %s\n",s));
|
||||
DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
|
||||
}
|
||||
|
||||
/* groups stuff added by ih */
|
||||
@ -634,7 +634,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
|
||||
I have disabled this chdir check (tridge) */
|
||||
if (vfs_ChDir(conn,conn->connectpath) != 0) {
|
||||
DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
|
||||
remote_machine, conn->client_address,
|
||||
get_remote_machine_name(), conn->client_address,
|
||||
conn->connectpath,strerror(errno)));
|
||||
change_to_root_user();
|
||||
yield_connection(conn, lp_servicename(SNUM(conn)));
|
||||
@ -645,7 +645,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
|
||||
#else
|
||||
/* the alternative is just to check the directory exists */
|
||||
if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
|
||||
DEBUG(0,("%s is not a directory\n", conn->connectpath));
|
||||
DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
|
||||
change_to_root_user();
|
||||
yield_connection(conn, lp_servicename(SNUM(conn)));
|
||||
conn_free(conn);
|
||||
@ -674,7 +674,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
|
||||
*/
|
||||
|
||||
if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
|
||||
dbgtext( "%s (%s) ", remote_machine, conn->client_address );
|
||||
dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
|
||||
dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
|
||||
dbgtext( "initially as user %s ", user );
|
||||
dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
|
||||
@ -759,6 +759,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
|
||||
vuser = get_valid_user_struct(vuid);
|
||||
if (!vuser) {
|
||||
DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
|
||||
*status = NT_STATUS_ACCESS_DENIED;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -773,12 +774,15 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
|
||||
if (strequal(service_in,HOMES_NAME)) {
|
||||
if(lp_security() != SEC_SHARE) {
|
||||
DATA_BLOB no_pw = data_blob(NULL, 0);
|
||||
if (vuser->homes_snum != -1) {
|
||||
DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
|
||||
return make_connection_snum(vuser->homes_snum,
|
||||
vuser, no_pw,
|
||||
dev, status);
|
||||
if (vuser->homes_snum == -1) {
|
||||
DEBUG(2, ("[homes] share not available for this user becouse it was not found or created at session setup time\n"));
|
||||
*status = NT_STATUS_BAD_NETWORK_NAME;
|
||||
return NULL;
|
||||
}
|
||||
DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
|
||||
return make_connection_snum(vuser->homes_snum,
|
||||
vuser, no_pw,
|
||||
dev, status);
|
||||
} else {
|
||||
/* Security = share. Try with current_user_info.smb_name
|
||||
* as the username. */
|
||||
@ -797,7 +801,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
|
||||
}
|
||||
}
|
||||
} else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
|
||||
&& strequal(service, lp_servicename(vuser->homes_snum))) {
|
||||
&& strequal(service_in, lp_servicename(vuser->homes_snum))) {
|
||||
DATA_BLOB no_pw = data_blob(NULL, 0);
|
||||
DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service));
|
||||
return make_connection_snum(vuser->homes_snum,
|
||||
@ -819,7 +823,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
|
||||
}
|
||||
|
||||
DEBUG(0,("%s (%s) couldn't find service %s\n",
|
||||
remote_machine, client_addr(), service));
|
||||
get_remote_machine_name(), client_addr(), service));
|
||||
*status = NT_STATUS_BAD_NETWORK_NAME;
|
||||
return NULL;
|
||||
}
|
||||
@ -841,7 +845,7 @@ void close_cnum(connection_struct *conn, uint16 vuid)
|
||||
change_to_root_user();
|
||||
|
||||
DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
|
||||
remote_machine,conn->client_address,
|
||||
get_remote_machine_name(),conn->client_address,
|
||||
lp_servicename(SNUM(conn))));
|
||||
|
||||
if (conn->vfs_ops.disconnect != NULL) {
|
||||
|
@ -27,21 +27,22 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
extern fstring remote_machine;
|
||||
|
||||
static TDB_CONTEXT *tdb;
|
||||
/* called when a session is created */
|
||||
BOOL session_claim(user_struct *vuser)
|
||||
{
|
||||
int i;
|
||||
int i = 0;
|
||||
TDB_DATA data;
|
||||
struct sessionid sessionid;
|
||||
uint32 pid = (uint32)sys_getpid();
|
||||
TDB_DATA key;
|
||||
fstring keystr;
|
||||
char * hostname;
|
||||
int tdb_store_flag; /* If using utmp, we do an inital 'lock hold' store,
|
||||
but we don't need this if we are just using the
|
||||
(unique) pid/vuid combination */
|
||||
|
||||
vuser->session_id = 0;
|
||||
vuser->session_keystr = NULL;
|
||||
|
||||
/* don't register sessions for the guest user - its just too
|
||||
expensive to go through pam session code for browsing etc */
|
||||
@ -63,18 +64,37 @@ BOOL session_claim(user_struct *vuser)
|
||||
data.dptr = NULL;
|
||||
data.dsize = 0;
|
||||
|
||||
for (i=1;i<MAX_SESSION_ID;i++) {
|
||||
slprintf(keystr, sizeof(keystr)-1, "ID/%d", i);
|
||||
#if WITH_UTMP
|
||||
if (lp_utmp()) {
|
||||
for (i=1;i<MAX_SESSION_ID;i++) {
|
||||
slprintf(keystr, sizeof(keystr)-1, "ID/%d", i);
|
||||
key.dptr = keystr;
|
||||
key.dsize = strlen(keystr)+1;
|
||||
|
||||
if (tdb_store(tdb, key, data, TDB_INSERT) == 0) break;
|
||||
}
|
||||
|
||||
if (i == MAX_SESSION_ID) {
|
||||
DEBUG(1,("session_claim: out of session IDs (max is %d)\n",
|
||||
MAX_SESSION_ID));
|
||||
return False;
|
||||
}
|
||||
slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_UTMP_TEMPLATE, i);
|
||||
tdb_store_flag = TDB_MODIFY;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
slprintf(keystr, sizeof(keystr)-1, "ID/%lu/%u",
|
||||
(long unsigned int)sys_getpid(),
|
||||
vuser->vuid);
|
||||
slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1,
|
||||
SESSION_TEMPLATE, (long unsigned int)sys_getpid(),
|
||||
vuser->vuid);
|
||||
|
||||
key.dptr = keystr;
|
||||
key.dsize = strlen(keystr)+1;
|
||||
|
||||
if (tdb_store(tdb, key, data, TDB_INSERT) == 0) break;
|
||||
}
|
||||
|
||||
if (i == MAX_SESSION_ID) {
|
||||
DEBUG(1,("session_claim: out of session IDs (max is %d)\n",
|
||||
MAX_SESSION_ID));
|
||||
return False;
|
||||
|
||||
tdb_store_flag = TDB_REPLACE;
|
||||
}
|
||||
|
||||
/* If 'hostname lookup' == yes, then do the DNS lookup. This is
|
||||
@ -90,24 +110,25 @@ BOOL session_claim(user_struct *vuser)
|
||||
|
||||
fstrcpy(sessionid.username, vuser->user.unix_name);
|
||||
fstrcpy(sessionid.hostname, hostname);
|
||||
slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_TEMPLATE, i);
|
||||
sessionid.id_num = i;
|
||||
sessionid.id_num = i; /* Only valid for utmp sessions */
|
||||
sessionid.pid = pid;
|
||||
sessionid.uid = vuser->uid;
|
||||
sessionid.gid = vuser->gid;
|
||||
fstrcpy(sessionid.remote_machine, remote_machine);
|
||||
fstrcpy(sessionid.remote_machine, get_remote_machine_name());
|
||||
fstrcpy(sessionid.ip_addr, client_addr());
|
||||
|
||||
if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) {
|
||||
DEBUG(1,("pam_session rejected the session for %s [%s]\n",
|
||||
sessionid.username, sessionid.id_str));
|
||||
tdb_delete(tdb, key);
|
||||
if (tdb_store_flag == TDB_MODIFY) {
|
||||
tdb_delete(tdb, key);
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
data.dptr = (char *)&sessionid;
|
||||
data.dsize = sizeof(sessionid);
|
||||
if (tdb_store(tdb, key, data, TDB_MODIFY) != 0) {
|
||||
if (tdb_store(tdb, key, data, tdb_store_flag) != 0) {
|
||||
DEBUG(1,("session_claim: unable to create session id record\n"));
|
||||
return False;
|
||||
}
|
||||
@ -119,7 +140,11 @@ BOOL session_claim(user_struct *vuser)
|
||||
}
|
||||
#endif
|
||||
|
||||
vuser->session_id = i;
|
||||
vuser->session_keystr = strdup(keystr);
|
||||
if (!vuser->session_keystr) {
|
||||
DEBUG(0, ("session_claim: strdup() failed for session_keystr\n"));
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
@ -129,18 +154,15 @@ void session_yield(user_struct *vuser)
|
||||
TDB_DATA dbuf;
|
||||
struct sessionid sessionid;
|
||||
TDB_DATA key;
|
||||
fstring keystr;
|
||||
|
||||
if (!tdb) return;
|
||||
|
||||
if (vuser->session_id == 0) {
|
||||
if (!vuser->session_keystr) {
|
||||
return;
|
||||
}
|
||||
|
||||
slprintf(keystr, sizeof(keystr)-1, "ID/%d", vuser->session_id);
|
||||
|
||||
key.dptr = keystr;
|
||||
key.dsize = strlen(keystr)+1;
|
||||
key.dptr = vuser->session_keystr;
|
||||
key.dsize = strlen(vuser->session_keystr)+1;
|
||||
|
||||
dbuf = tdb_fetch(tdb, key);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
handle SMBsessionsetup
|
||||
Copyright (C) Andrew Tridgell 1998-2001
|
||||
Copyright (C) Andrew Bartlett 2001
|
||||
Copyright (C) Jim McDonough 2002
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -122,6 +123,12 @@ static int reply_spnego_kerberos(connection_struct *conn,
|
||||
|
||||
ads = ads_init_simple();
|
||||
|
||||
if (!ads) {
|
||||
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
|
||||
}
|
||||
|
||||
ads->auth.realm = strdup(lp_realm());
|
||||
|
||||
ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(1,("Failed to verify incoming ticket!\n"));
|
||||
@ -139,7 +146,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
if (strcasecmp(p+1, ads->realm) != 0) {
|
||||
if (strcasecmp(p+1, ads->auth.realm) != 0) {
|
||||
DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
|
||||
if (!lp_allow_trusted_domains()) {
|
||||
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
|
||||
@ -200,7 +207,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
|
||||
send a security blob via a session setup reply
|
||||
****************************************************************************/
|
||||
static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
|
||||
DATA_BLOB blob)
|
||||
DATA_BLOB blob, uint32 errcode)
|
||||
{
|
||||
char *p;
|
||||
|
||||
@ -209,7 +216,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
|
||||
/* we set NT_STATUS_MORE_PROCESSING_REQUIRED to tell the other end
|
||||
that we aren't finished yet */
|
||||
|
||||
SIVAL(outbuf, smb_rcls, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
|
||||
SIVAL(outbuf, smb_rcls, errcode);
|
||||
SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
|
||||
SSVAL(outbuf, smb_vwv3, blob.length);
|
||||
p = smb_buf(outbuf);
|
||||
@ -236,11 +243,12 @@ static int reply_spnego_negotiate(connection_struct *conn,
|
||||
DATA_BLOB secblob;
|
||||
int i;
|
||||
uint32 ntlmssp_command, neg_flags, chal_flags;
|
||||
DATA_BLOB chal, spnego_chal, extra_data;
|
||||
DATA_BLOB chal, spnego_chal;
|
||||
const uint8 *cryptkey;
|
||||
BOOL got_kerberos = False;
|
||||
NTSTATUS nt_status;
|
||||
extern pstring global_myname;
|
||||
char *cliname=NULL, *domname=NULL;
|
||||
|
||||
/* parse out the OIDs and the first sec blob */
|
||||
if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
|
||||
@ -258,7 +266,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
|
||||
DEBUG(3,("Got secblob of size %d\n", secblob.length));
|
||||
|
||||
#ifdef HAVE_KRB5
|
||||
if (got_kerberos) {
|
||||
if (got_kerberos && (SEC_ADS == lp_security())) {
|
||||
int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
|
||||
length, bufsize, &secblob);
|
||||
data_blob_free(&secblob);
|
||||
@ -271,19 +279,16 @@ static int reply_spnego_negotiate(connection_struct *conn,
|
||||
file_save("secblob.dat", secblob.data, secblob.length);
|
||||
#endif
|
||||
|
||||
if (!msrpc_parse(&secblob, "CddB",
|
||||
if (!msrpc_parse(&secblob, "CddAA",
|
||||
"NTLMSSP",
|
||||
&ntlmssp_command,
|
||||
&neg_flags,
|
||||
&extra_data)) {
|
||||
&cliname,
|
||||
&domname)) {
|
||||
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
|
||||
}
|
||||
|
||||
DEBUG(5, ("Extra data: \n"));
|
||||
dump_data(5, extra_data.data, extra_data.length);
|
||||
|
||||
data_blob_free(&secblob);
|
||||
data_blob_free(&extra_data);
|
||||
|
||||
if (ntlmssp_command != NTLMSSP_NEGOTIATE) {
|
||||
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
|
||||
@ -307,41 +312,44 @@ static int reply_spnego_negotiate(connection_struct *conn,
|
||||
return the flags we want. Obviously this is not correct */
|
||||
|
||||
chal_flags = NTLMSSP_NEGOTIATE_UNICODE |
|
||||
NTLMSSP_NEGOTIATE_LM_KEY |
|
||||
NTLMSSP_NEGOTIATE_128 |
|
||||
NTLMSSP_NEGOTIATE_NTLM |
|
||||
NTLMSSP_CHAL_TARGET_INFO;
|
||||
|
||||
{
|
||||
DATA_BLOB domain_blob, netbios_blob, realm_blob;
|
||||
DATA_BLOB domain_blob, struct_blob;
|
||||
fstring dnsname, dnsdomname;
|
||||
|
||||
msrpc_gen(&domain_blob,
|
||||
"U",
|
||||
lp_workgroup());
|
||||
|
||||
msrpc_gen(&netbios_blob,
|
||||
"U",
|
||||
global_myname);
|
||||
|
||||
msrpc_gen(&realm_blob,
|
||||
"U",
|
||||
lp_realm());
|
||||
|
||||
fstrcpy(dnsdomname, lp_realm());
|
||||
strlower(dnsdomname);
|
||||
|
||||
msrpc_gen(&chal, "CddddbBBBB",
|
||||
fstrcpy(dnsname, global_myname);
|
||||
fstrcat(dnsname, ".");
|
||||
fstrcat(dnsname, lp_realm());
|
||||
strlower(dnsname);
|
||||
|
||||
msrpc_gen(&struct_blob, "aaaaa",
|
||||
2, lp_workgroup(),
|
||||
1, global_myname,
|
||||
4, dnsdomname,
|
||||
3, dnsname,
|
||||
0, "");
|
||||
|
||||
msrpc_gen(&chal, "CdUdbddB",
|
||||
"NTLMSSP",
|
||||
NTLMSSP_CHALLENGE,
|
||||
0,
|
||||
0x30, /* ?? */
|
||||
lp_workgroup(),
|
||||
chal_flags,
|
||||
cryptkey, 8,
|
||||
domain_blob.data, domain_blob.length,
|
||||
domain_blob.data, domain_blob.length,
|
||||
netbios_blob.data, netbios_blob.length,
|
||||
realm_blob.data, realm_blob.length);
|
||||
0, 0,
|
||||
struct_blob.data, struct_blob.length);
|
||||
|
||||
data_blob_free(&domain_blob);
|
||||
data_blob_free(&netbios_blob);
|
||||
data_blob_free(&realm_blob);
|
||||
data_blob_free(&struct_blob);
|
||||
}
|
||||
|
||||
if (!spnego_gen_challenge(&spnego_chal, &chal, &chal)) {
|
||||
@ -351,7 +359,7 @@ static int reply_spnego_negotiate(connection_struct *conn,
|
||||
}
|
||||
|
||||
/* now tell the client to send the auth packet */
|
||||
reply_sesssetup_blob(conn, outbuf, spnego_chal);
|
||||
reply_sesssetup_blob(conn, outbuf, spnego_chal, NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED));
|
||||
|
||||
data_blob_free(&chal);
|
||||
data_blob_free(&spnego_chal);
|
||||
@ -368,7 +376,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
int length, int bufsize,
|
||||
DATA_BLOB blob1)
|
||||
{
|
||||
DATA_BLOB auth;
|
||||
DATA_BLOB auth, response;
|
||||
char *workgroup = NULL, *user = NULL, *machine = NULL;
|
||||
DATA_BLOB lmhash, nthash, sess_key;
|
||||
DATA_BLOB plaintext_password = data_blob(NULL, 0);
|
||||
@ -413,6 +421,13 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
|
||||
user, workgroup, machine, lmhash.length, nthash.length));
|
||||
|
||||
/* the client has given us its machine name (which we otherwise would not get on port 445).
|
||||
we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
|
||||
|
||||
set_remote_machine_name(machine);
|
||||
|
||||
reload_services(True);
|
||||
|
||||
#if 0
|
||||
file_save("nthash1.dat", nthash.data, nthash.length);
|
||||
file_save("lmhash1.dat", lmhash.data, lmhash.length);
|
||||
@ -481,8 +496,12 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
|
||||
SSVAL(outbuf,smb_uid,sess_vuid);
|
||||
SSVAL(inbuf,smb_uid,sess_vuid);
|
||||
|
||||
return chain_reply(inbuf,outbuf,length,bufsize);
|
||||
|
||||
response = spnego_gen_auth_response();
|
||||
reply_sesssetup_blob(conn, outbuf, response, 0);
|
||||
|
||||
/* and tell smbd that we have already replied to this packet */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -594,7 +613,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
extern BOOL global_encrypted_passwords_negotiated;
|
||||
extern BOOL global_spnego_negotiated;
|
||||
extern int Protocol;
|
||||
extern fstring remote_machine;
|
||||
extern userdom_struct current_user_info;
|
||||
extern int max_send;
|
||||
|
||||
@ -630,8 +648,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
|
||||
if (Protocol < PROTOCOL_NT1) {
|
||||
uint16 passlen1 = SVAL(inbuf,smb_vwv7);
|
||||
if (passlen1 > MAX_PASS_LEN) {
|
||||
return ERROR_DOS(ERRDOS,ERRbuftoosmall);
|
||||
if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (doencrypt) {
|
||||
@ -665,13 +683,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
}
|
||||
}
|
||||
|
||||
if (passlen1 > MAX_PASS_LEN) {
|
||||
return ERROR_DOS(ERRDOS,ERRbuftoosmall);
|
||||
}
|
||||
|
||||
passlen1 = MIN(passlen1, MAX_PASS_LEN);
|
||||
passlen2 = MIN(passlen2, MAX_PASS_LEN);
|
||||
|
||||
if (!doencrypt) {
|
||||
/* both Win95 and WinNT stuff up the password lengths for
|
||||
non-encrypting systems. Uggh.
|
||||
@ -689,19 +700,29 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
passlen2 = 0;
|
||||
}
|
||||
|
||||
/* check for nasty tricks */
|
||||
if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/* Save the lanman2 password and the NT md4 password. */
|
||||
|
||||
if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
|
||||
doencrypt = False;
|
||||
}
|
||||
|
||||
|
||||
if (doencrypt) {
|
||||
lm_resp = data_blob(p, passlen1);
|
||||
nt_resp = data_blob(p+passlen1, passlen2);
|
||||
} else {
|
||||
plaintext_password = data_blob(p, passlen1+1);
|
||||
/* Ensure null termination */
|
||||
plaintext_password.data[passlen1] = 0;
|
||||
pstring pass;
|
||||
srvstr_pull(inbuf, pass, smb_buf(inbuf),
|
||||
sizeof(pass), passlen1, STR_TERMINATE);
|
||||
plaintext_password = data_blob(pass, strlen(pass)+1);
|
||||
}
|
||||
|
||||
p += passlen1 + passlen2;
|
||||
@ -720,7 +741,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
|
||||
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
|
||||
}
|
||||
|
||||
DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine));
|
||||
DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
|
||||
|
||||
if (*user) {
|
||||
if (global_spnego_negotiated) {
|
||||
|
@ -30,6 +30,19 @@ extern int global_oplock_break;
|
||||
extern uint32 global_client_caps;
|
||||
extern pstring global_myname;
|
||||
|
||||
/* given a stat buffer return the allocated size on disk, taking into
|
||||
account sparse files */
|
||||
SMB_OFF_T get_allocation_size(SMB_STRUCT_STAT *sbuf)
|
||||
{
|
||||
SMB_OFF_T ret;
|
||||
ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
|
||||
ret = SMB_ROUNDUP_ALLOCATION(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define get_file_size(sbuf) (sbuf.st_size)
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Send the required number of replies back.
|
||||
We assume all fields other than the data fields are
|
||||
@ -256,7 +269,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
}
|
||||
|
||||
size = sbuf.st_size;
|
||||
size = get_file_size(sbuf);
|
||||
fmode = dos_mode(conn,fname,&sbuf);
|
||||
mtime = sbuf.st_mtime;
|
||||
inode = sbuf.st_ino;
|
||||
@ -453,7 +466,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
uint32 reskey=0;
|
||||
int prev_dirpos=0;
|
||||
int mode=0;
|
||||
SMB_OFF_T size = 0;
|
||||
SMB_OFF_T file_size = 0;
|
||||
SMB_OFF_T allocation_size = 0;
|
||||
uint32 len;
|
||||
time_t mdate=0, adate=0, cdate=0;
|
||||
@ -565,8 +578,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
continue;
|
||||
}
|
||||
|
||||
size = sbuf.st_size;
|
||||
allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
|
||||
file_size = get_file_size(sbuf);
|
||||
allocation_size = get_allocation_size(&sbuf);
|
||||
mdate = sbuf.st_mtime;
|
||||
adate = sbuf.st_atime;
|
||||
cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
|
||||
@ -578,7 +591,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
}
|
||||
|
||||
if(mode & aDIR)
|
||||
size = 0;
|
||||
file_size = 0;
|
||||
|
||||
DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
|
||||
|
||||
@ -602,7 +615,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
put_dos_date2(p,l1_fdateCreation,cdate);
|
||||
put_dos_date2(p,l1_fdateLastAccess,adate);
|
||||
put_dos_date2(p,l1_fdateLastWrite,mdate);
|
||||
SIVAL(p,l1_cbFile,(uint32)size);
|
||||
SIVAL(p,l1_cbFile,(uint32)file_size);
|
||||
SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
|
||||
SSVAL(p,l1_attrFile,mode);
|
||||
p += l1_achName;
|
||||
@ -621,7 +634,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
put_dos_date2(p,l2_fdateCreation,cdate);
|
||||
put_dos_date2(p,l2_fdateLastAccess,adate);
|
||||
put_dos_date2(p,l2_fdateLastWrite,mdate);
|
||||
SIVAL(p,l2_cbFile,(uint32)size);
|
||||
SIVAL(p,l2_cbFile,(uint32)file_size);
|
||||
SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
|
||||
SSVAL(p,l2_attrFile,mode);
|
||||
SIVAL(p,l2_cbList,0); /* No extended attributes */
|
||||
@ -641,7 +654,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
put_long_date(p,adate); p += 8;
|
||||
put_long_date(p,mdate); p += 8;
|
||||
put_long_date(p,mdate); p += 8;
|
||||
SOFF_T(p,0,size);
|
||||
SOFF_T(p,0,file_size);
|
||||
SOFF_T(p,8,allocation_size);
|
||||
p += 16;
|
||||
SIVAL(p,0,nt_extmode); p += 4;
|
||||
@ -675,7 +688,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
put_long_date(p,adate); p += 8;
|
||||
put_long_date(p,mdate); p += 8;
|
||||
put_long_date(p,mdate); p += 8;
|
||||
SOFF_T(p,0,size);
|
||||
SOFF_T(p,0,file_size);
|
||||
SOFF_T(p,8,allocation_size);
|
||||
p += 16;
|
||||
SIVAL(p,0,nt_extmode); p += 4;
|
||||
@ -696,7 +709,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
put_long_date(p,adate); p += 8;
|
||||
put_long_date(p,mdate); p += 8;
|
||||
put_long_date(p,mdate); p += 8;
|
||||
SOFF_T(p,0,size);
|
||||
SOFF_T(p,0,file_size);
|
||||
SOFF_T(p,8,allocation_size);
|
||||
p += 16;
|
||||
SIVAL(p,0,nt_extmode); p += 4;
|
||||
@ -735,14 +748,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
|
||||
SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
|
||||
|
||||
/* Begin of SMB_QUERY_FILE_UNIX_BASIC */
|
||||
SOFF_T(p,0,sbuf.st_size); /* File size 64 Bit */
|
||||
SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
|
||||
p+= 8;
|
||||
|
||||
#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
|
||||
SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
|
||||
#else
|
||||
/* Can't get the value - fake it using size. */
|
||||
SOFF_T(p,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
|
||||
SOFF_T(p,0,get_file_size(sbuf)); /* Number of bytes used on disk - 64 Bit */
|
||||
#endif
|
||||
p+= 8;
|
||||
|
||||
@ -1528,7 +1541,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
uint16 tran_call = SVAL(inbuf, smb_setup0);
|
||||
uint16 info_level;
|
||||
int mode=0;
|
||||
SMB_OFF_T size=0;
|
||||
SMB_OFF_T file_size=0;
|
||||
SMB_OFF_T allocation_size=0;
|
||||
unsigned int data_size;
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
@ -1643,10 +1656,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
|
||||
mode = dos_mode(conn,fname,&sbuf);
|
||||
fullpathname = fname;
|
||||
size = sbuf.st_size;
|
||||
allocation_size = SMB_ROUNDUP_ALLOCATION(sbuf.st_size);
|
||||
file_size = get_file_size(sbuf);
|
||||
allocation_size = get_allocation_size(&sbuf);
|
||||
if (mode & aDIR)
|
||||
size = 0;
|
||||
file_size = 0;
|
||||
|
||||
params = Realloc(*pparams,2);
|
||||
if (params == NULL)
|
||||
@ -1692,7 +1705,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
put_dos_date2(pdata,l1_fdateCreation,c_time);
|
||||
put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
|
||||
put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
|
||||
SIVAL(pdata,l1_cbFile,(uint32)size);
|
||||
SIVAL(pdata,l1_cbFile,(uint32)file_size);
|
||||
SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
|
||||
SSVAL(pdata,l1_attrFile,mode);
|
||||
SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
|
||||
@ -1703,7 +1716,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
put_dos_date2(pdata,0,c_time);
|
||||
put_dos_date2(pdata,4,sbuf.st_atime);
|
||||
put_dos_date2(pdata,8,sbuf.st_mtime);
|
||||
SIVAL(pdata,12,(uint32)size);
|
||||
SIVAL(pdata,12,(uint32)file_size);
|
||||
SIVAL(pdata,16,(uint32)allocation_size);
|
||||
SIVAL(pdata,20,mode);
|
||||
break;
|
||||
@ -1747,9 +1760,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
case SMB_QUERY_FILE_STANDARD_INFO:
|
||||
|
||||
data_size = 24;
|
||||
/* Fake up allocation size. */
|
||||
SOFF_T(pdata,0,allocation_size);
|
||||
SOFF_T(pdata,8,size);
|
||||
SOFF_T(pdata,8,file_size);
|
||||
SIVAL(pdata,16,sbuf.st_nlink);
|
||||
SCVAL(pdata,20,0);
|
||||
SCVAL(pdata,21,(mode&aDIR)?1:0);
|
||||
@ -1794,7 +1806,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
case SMB_FILE_END_OF_FILE_INFORMATION:
|
||||
case SMB_QUERY_FILE_END_OF_FILEINFO:
|
||||
data_size = 8;
|
||||
SOFF_T(pdata,0,size);
|
||||
SOFF_T(pdata,0,file_size);
|
||||
break;
|
||||
|
||||
case SMB_QUERY_FILE_ALL_INFO:
|
||||
@ -1805,7 +1817,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
SIVAL(pdata,32,mode);
|
||||
pdata += 40;
|
||||
SOFF_T(pdata,0,allocation_size);
|
||||
SOFF_T(pdata,8,size);
|
||||
SOFF_T(pdata,8,file_size);
|
||||
SIVAL(pdata,16,sbuf.st_nlink);
|
||||
SCVAL(pdata,20,delete_pending);
|
||||
SCVAL(pdata,21,(mode&aDIR)?1:0);
|
||||
@ -1917,7 +1929,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
|
||||
SIVAL(pdata,0,0); /* ??? */
|
||||
SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
|
||||
SOFF_T(pdata,8,size);
|
||||
SOFF_T(pdata,8,file_size);
|
||||
SIVAL(pdata,16,allocation_size);
|
||||
SIVAL(pdata,20,0); /* ??? */
|
||||
data_size = 24 + byte_len;
|
||||
@ -1925,7 +1937,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
break;
|
||||
|
||||
case SMB_FILE_COMPRESSION_INFORMATION:
|
||||
SOFF_T(pdata,0,size);
|
||||
SOFF_T(pdata,0,allocation_size);
|
||||
SIVAL(pdata,8,0); /* ??? */
|
||||
SIVAL(pdata,12,0); /* ??? */
|
||||
data_size = 16;
|
||||
@ -1937,7 +1949,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
put_long_date(pdata+16,sbuf.st_mtime); /* write time */
|
||||
put_long_date(pdata+24,sbuf.st_mtime); /* change time */
|
||||
SIVAL(pdata,32,allocation_size);
|
||||
SOFF_T(pdata,40,size);
|
||||
SOFF_T(pdata,40,file_size);
|
||||
SIVAL(pdata,48,mode);
|
||||
SIVAL(pdata,52,0); /* ??? */
|
||||
data_size = 56;
|
||||
@ -1957,14 +1969,14 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
|
||||
|
||||
DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
|
||||
|
||||
SOFF_T(pdata,0,sbuf.st_size); /* File size 64 Bit */
|
||||
SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
|
||||
pdata += 8;
|
||||
|
||||
#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
|
||||
SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
|
||||
#else
|
||||
/* Can't get the value - fake it using size. */
|
||||
SOFF_T(pdata,0,sbuf.st_size); /* Number of bytes used on disk - 64 Bit */
|
||||
SOFF_T(pdata,0,get_file_size(sbuf)); /* Number of bytes used on disk - 64 Bit */
|
||||
#endif
|
||||
pdata += 8;
|
||||
|
||||
@ -2246,7 +2258,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
|
||||
SSVAL(params,0,0);
|
||||
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
|
||||
return(-1);
|
||||
}
|
||||
} else
|
||||
return (UNIXERROR(ERRDOS,ERRbadpath));
|
||||
} else {
|
||||
/*
|
||||
* Original code - this is an open file.
|
||||
@ -2310,7 +2323,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
|
||||
sbuf.st_mtime = fsp->pending_modtime;
|
||||
}
|
||||
|
||||
size = sbuf.st_size;
|
||||
size = get_file_size(sbuf);
|
||||
tvs.modtime = sbuf.st_mtime;
|
||||
tvs.actime = sbuf.st_atime;
|
||||
dosmode = dos_mode(conn,fname,&sbuf);
|
||||
@ -2413,7 +2426,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
|
||||
DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
|
||||
fname, (double)allocation_size ));
|
||||
|
||||
if(allocation_size != sbuf.st_size) {
|
||||
if(allocation_size != get_file_size(sbuf)) {
|
||||
SMB_STRUCT_STAT new_sbuf;
|
||||
|
||||
DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
|
||||
@ -2459,8 +2472,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
|
||||
if (ret == -1)
|
||||
return ERROR_NT(NT_STATUS_DISK_FULL);
|
||||
|
||||
/* Allocate can trucate size... */
|
||||
size = new_sbuf.st_size;
|
||||
/* Allocate can truncate size... */
|
||||
size = get_file_size(new_sbuf);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -2715,7 +2728,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
* changing the size of a file.
|
||||
*/
|
||||
if (!size)
|
||||
size = sbuf.st_size;
|
||||
size = get_file_size(sbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2757,7 +2770,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
}
|
||||
}
|
||||
|
||||
if(size != sbuf.st_size) {
|
||||
if (size != get_file_size(sbuf)) {
|
||||
|
||||
int ret;
|
||||
|
||||
@ -2970,9 +2983,11 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf,
|
||||
{
|
||||
char *pdata = *ppdata;
|
||||
files_struct *fsp = file_fsp(inbuf,smb_vwv15);
|
||||
|
||||
|
||||
if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
|
||||
(SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
|
||||
uint16 rap_jobid;
|
||||
|
||||
pdata = Realloc(*ppdata, 32);
|
||||
if(pdata == NULL)
|
||||
return ERROR_DOS(ERRDOS,ERRnomem);
|
||||
@ -2981,7 +2996,8 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf,
|
||||
/* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
|
||||
CAN ACCEPT THIS IN UNICODE. JRA. */
|
||||
|
||||
SSVAL(pdata,0,fsp->print_jobid); /* Job number */
|
||||
rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid); /* Job number */
|
||||
SSVAL(pdata,0,rap_jobid); /* Job number */
|
||||
srvstr_push( outbuf, pdata + 2, global_myname, 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
|
||||
srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
|
||||
send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
|
||||
|
@ -440,44 +440,43 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N
|
||||
extern pstring global_myname;
|
||||
extern fstring global_myworkgroup;
|
||||
fstring sid;
|
||||
BOOL ret = False;
|
||||
BOOL local_lookup = False;
|
||||
|
||||
*name_type = SID_NAME_UNKNOWN;
|
||||
|
||||
/* If we are looking up a domain user, make sure it is
|
||||
for the local machine only */
|
||||
|
||||
switch (lp_server_role()) {
|
||||
case ROLE_DOMAIN_PDC:
|
||||
case ROLE_DOMAIN_BDC:
|
||||
if (strequal(global_myname, domain)) {
|
||||
local_lookup = True;
|
||||
} else if (lp_server_role() == ROLE_DOMAIN_PDC ||
|
||||
lp_server_role() == ROLE_DOMAIN_PDC) {
|
||||
if (strequal(domain, global_myworkgroup)) {
|
||||
ret = local_lookup_name(name, psid, name_type);
|
||||
local_lookup = True;
|
||||
}
|
||||
/* No break is deliberate here. JRA. */
|
||||
default:
|
||||
if (ret) {
|
||||
} else if (strequal(global_myname, domain)) {
|
||||
ret = local_lookup_name(name, psid, name_type);
|
||||
} else {
|
||||
DEBUG(5, ("lookup_name: domain %s is not local\n", domain));
|
||||
}
|
||||
|
||||
if (local_lookup) {
|
||||
if (local_lookup_name(name, psid, name_type)) {
|
||||
DEBUG(10,
|
||||
("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
|
||||
domain, name, sid_to_string(sid,psid),
|
||||
sid_type_lookup(*name_type), (unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
} else {
|
||||
/* Remote */
|
||||
if (winbind_lookup_name(domain, name, psid, name_type)) {
|
||||
|
||||
DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n",
|
||||
domain, name, sid_to_string(sid, psid),
|
||||
(unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
DEBUG(10,
|
||||
("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n",
|
||||
domain, name, sid_to_string(sid,psid),
|
||||
sid_type_lookup(*name_type), (unsigned int)*name_type));
|
||||
return True;
|
||||
} else if (winbind_lookup_name(domain, name, psid, name_type)) {
|
||||
|
||||
DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n",
|
||||
domain, name, sid_to_string(sid, psid),
|
||||
(unsigned int)*name_type));
|
||||
return True;
|
||||
}
|
||||
|
||||
DEBUG(10, ("lookup_name: winbind and local lookups for [%s]\\[%s] failed\n", domain, name));
|
||||
DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n",
|
||||
local_lookup ? "local" : "winbind", domain, name));
|
||||
|
||||
return False;
|
||||
}
|
||||
@ -593,13 +592,17 @@ DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid)
|
||||
was done correctly, False if not. sidtype is set by this function.
|
||||
*****************************************************************/
|
||||
|
||||
BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
|
||||
BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
|
||||
{
|
||||
fstring sid_str;
|
||||
|
||||
/* if we know its local then don't try winbindd */
|
||||
if (sid_compare_domain(get_global_sam_sid(), psid) == 0) {
|
||||
return local_sid_to_uid(puid, psid, sidtype);
|
||||
BOOL result;
|
||||
become_root();
|
||||
result = local_sid_to_uid(puid, psid, sidtype);
|
||||
unbecome_root();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (tridge) I commented out the slab of code below in order to support foreign SIDs
|
||||
@ -665,7 +668,7 @@ BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
|
||||
was done correctly, False if not.
|
||||
*****************************************************************/
|
||||
|
||||
BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
|
||||
BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
|
||||
{
|
||||
fstring dom_name, name, sid_str;
|
||||
enum SID_NAME_USE name_type;
|
||||
@ -676,16 +679,21 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
|
||||
* First we must look up the name and decide if this is a group sid.
|
||||
*/
|
||||
|
||||
/* if we know its local then don't try winbindd */
|
||||
if (sid_compare_domain(get_global_sam_sid(), psid) == 0) {
|
||||
BOOL result;
|
||||
become_root();
|
||||
result = local_sid_to_gid(pgid, psid, sidtype);
|
||||
unbecome_root();
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
|
||||
DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
|
||||
DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n",
|
||||
sid_to_string(sid_str, psid) ));
|
||||
if (!local_sid_to_gid(pgid, psid, sidtype)) {
|
||||
/* this was probably a foreign sid - assume its a group rid
|
||||
and continue */
|
||||
name_type = SID_NAME_DOM_GRP;
|
||||
} else {
|
||||
return True;
|
||||
}
|
||||
/* this was probably a foreign sid - assume its a group rid
|
||||
and continue */
|
||||
name_type = SID_NAME_DOM_GRP;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -696,7 +704,7 @@ BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
|
||||
DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
|
||||
(unsigned int)name_type ));
|
||||
|
||||
return local_sid_to_gid(pgid, psid, sidtype);
|
||||
return False;
|
||||
}
|
||||
|
||||
*sidtype = name_type;
|
||||
|
@ -3,6 +3,7 @@
|
||||
Version 1.9.
|
||||
VFS initialisation and support functions
|
||||
Copyright (C) Tim Potter 1999
|
||||
Copyright (C) Alexander Bokovoy 2002
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -17,6 +18,8 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
This work was sponsored by Optifacio Software Services, Inc.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
@ -28,6 +31,12 @@ struct vfs_syminfo {
|
||||
void *fptr;
|
||||
};
|
||||
|
||||
/*
|
||||
Opaque (final) vfs operations. This is a combination of first-met opaque vfs operations
|
||||
across all currently processed modules. */
|
||||
|
||||
static vfs_op_tuple vfs_opaque_ops[SMB_VFS_OP_LAST];
|
||||
|
||||
/* Default vfs hooks. WARNING: The order of these initialisers is
|
||||
very important. They must be in the same order as defined in
|
||||
vfs.h. Change at your own peril. */
|
||||
@ -117,58 +126,75 @@ static struct vfs_ops default_vfs_ops = {
|
||||
initialise default vfs hooks
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL vfs_init_default(connection_struct *conn)
|
||||
static void vfs_init_default(connection_struct *conn)
|
||||
{
|
||||
DEBUG(3, ("Initialising default vfs hooks\n"));
|
||||
|
||||
memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops));
|
||||
return True;
|
||||
conn->vfs_private = NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
initialise custom vfs hooks
|
||||
****************************************************************************/
|
||||
|
||||
static BOOL vfs_init_custom(connection_struct *conn)
|
||||
static BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
|
||||
{
|
||||
int vfs_version = -1;
|
||||
struct vfs_ops *ops, *(*init_fptr)(int *, struct vfs_ops *);
|
||||
vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *);
|
||||
int i;
|
||||
|
||||
DEBUG(3, ("Initialising custom vfs hooks from %s\n", lp_vfsobj(SNUM(conn))));
|
||||
DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object));
|
||||
|
||||
/* Open object file */
|
||||
|
||||
if ((conn->dl_handle = sys_dlopen(lp_vfsobj(SNUM(conn)), RTLD_NOW | RTLD_GLOBAL)) == NULL) {
|
||||
DEBUG(0, ("Error opening %s: %s\n", lp_vfsobj(SNUM(conn)), sys_dlerror()));
|
||||
if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) {
|
||||
DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror()));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Get handle on vfs_init() symbol */
|
||||
|
||||
init_fptr = (struct vfs_ops *(*)(int *, struct vfs_ops *))sys_dlsym(conn->dl_handle, "vfs_init");
|
||||
init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init");
|
||||
|
||||
if (init_fptr == NULL) {
|
||||
DEBUG(0, ("No vfs_init() symbol found in %s\n", lp_vfsobj(SNUM(conn))));
|
||||
DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Initialise vfs_ops structure */
|
||||
|
||||
conn->vfs_ops = default_vfs_ops;
|
||||
|
||||
if ((ops = init_fptr(&vfs_version, &default_vfs_ops)) == NULL) {
|
||||
DEBUG(0, ("vfs_init function from %s failed\n", lp_vfsobj(SNUM(conn))));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (vfs_version != SMB_VFS_INTERFACE_VERSION) {
|
||||
DEBUG(0, ("vfs_init returned wrong interface version info (was %d, should be %d)\n",
|
||||
vfs_version, SMB_VFS_INTERFACE_VERSION ));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (ops != &conn->vfs_ops) {
|
||||
memcpy(&conn->vfs_ops, ops, sizeof(struct vfs_ops));
|
||||
if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) {
|
||||
DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object));
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) {
|
||||
DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n",
|
||||
vfs_version, SMB_VFS_INTERFACE_VERSION ));
|
||||
return False;
|
||||
}
|
||||
|
||||
if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) {
|
||||
DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\
|
||||
Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n",
|
||||
vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version ));
|
||||
return False;
|
||||
}
|
||||
|
||||
for(i=0; ops[i].op != NULL; i++) {
|
||||
DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
|
||||
if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
|
||||
/* Check whether this operation was already made opaque by different module */
|
||||
if(vfs_opaque_ops[ops[i].type].op == ((void**)&default_vfs_ops)[ops[i].type]) {
|
||||
/* No, it isn't overloaded yet. Overload. */
|
||||
DEBUG(3, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
|
||||
vfs_opaque_ops[ops[i].type] = ops[i];
|
||||
}
|
||||
}
|
||||
/* Change current VFS disposition*/
|
||||
DEBUG(3, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object));
|
||||
((void**)&conn->vfs_ops)[ops[i].type] = ops[i].op;
|
||||
}
|
||||
|
||||
return True;
|
||||
@ -180,21 +206,70 @@ static BOOL vfs_init_custom(connection_struct *conn)
|
||||
|
||||
BOOL smbd_vfs_init(connection_struct *conn)
|
||||
{
|
||||
if (*lp_vfsobj(SNUM(conn))) {
|
||||
|
||||
/* Loadable object file */
|
||||
|
||||
if (!vfs_init_custom(conn)) {
|
||||
DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
char **vfs_objects, *vfsobj, *vfs_module, *vfs_path;
|
||||
int nobj, i;
|
||||
struct smb_vfs_handle_struct *handle;
|
||||
|
||||
/* Normal share - initialise with disk access functions */
|
||||
|
||||
return vfs_init_default(conn);
|
||||
vfs_init_default(conn);
|
||||
|
||||
/* Override VFS functions if 'vfs object' was specified*/
|
||||
if (*lp_vfsobj(SNUM(conn))) {
|
||||
vfsobj = NULL;
|
||||
for(i=0; i<SMB_VFS_OP_LAST; i++) {
|
||||
vfs_opaque_ops[i].op = ((void**)&default_vfs_ops)[i];
|
||||
vfs_opaque_ops[i].type = i;
|
||||
vfs_opaque_ops[i].layer = SMB_VFS_LAYER_OPAQUE;
|
||||
}
|
||||
if (string_set(&vfsobj, lp_vfsobj(SNUM(conn)))) {
|
||||
/* Parse passed modules specification to array of modules */
|
||||
set_first_token(vfsobj);
|
||||
/* We are using default separators: ' \t\r\n' */
|
||||
vfs_objects = toktocliplist(&nobj, NULL);
|
||||
if (vfs_objects) {
|
||||
vfs_path = lp_vfs_path(SNUM(conn));
|
||||
conn->vfs_private = NULL;
|
||||
for(i=nobj-1; i>=0; i--) {
|
||||
handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct));
|
||||
/* Loadable object file */
|
||||
handle->handle = NULL;
|
||||
DLIST_ADD(conn->vfs_private, handle)
|
||||
vfs_module = NULL;
|
||||
if (vfs_path) {
|
||||
asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[i]);
|
||||
} else {
|
||||
asprintf(&vfs_module, "%s", vfs_objects[i]);
|
||||
}
|
||||
if (!vfs_init_custom(conn, vfs_module)) {
|
||||
DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module));
|
||||
string_free(&vfsobj);
|
||||
SAFE_FREE(vfs_module);
|
||||
return False;
|
||||
}
|
||||
SAFE_FREE(vfs_module);
|
||||
}
|
||||
}
|
||||
string_free(&vfsobj);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Create vfs_ops reflecting current vfs_opaque_ops
|
||||
*******************************************************************/
|
||||
struct vfs_ops *smb_vfs_get_opaque_ops(void)
|
||||
{
|
||||
int i;
|
||||
struct vfs_ops *ops;
|
||||
|
||||
ops = smb_xmalloc(sizeof(struct vfs_ops));
|
||||
|
||||
for(i=0; i<SMB_VFS_OP_LAST; i++) {
|
||||
((void**)ops)[i] = vfs_opaque_ops[i].op;
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
Loading…
x
Reference in New Issue
Block a user