summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2004-03-01 16:10:28 +0000
committerSimo Sorce <idra@samba.org>2004-03-01 16:10:28 +0000
commiteebc94d84af736bb1fdd8e0c511237b0da978e7a (patch)
tree3d39c50ac039a7fc56d677b90e60421f7d6fc878 /source3/smbd
parentf986f33aa13f8672e2154f29906f657c023777dc (diff)
downloadsamba-eebc94d84af736bb1fdd8e0c511237b0da978e7a.tar.gz
samba-eebc94d84af736bb1fdd8e0c511237b0da978e7a.tar.bz2
samba-eebc94d84af736bb1fdd8e0c511237b0da978e7a.zip
Ok here it is my latest work on privileges
This patch add privilege support for samba Currently it is implemented only for tdbsam backend but estending it to other sam backends is straightforward. I must make a big thank to JFM for his teachings on the matter and the functions at the base of this work. At thye moment only samr_create_user honours SeAddUsersPrivilege and SeMachineAccountPrivilege to permit any user to add machines and/or users to the server. The command "net priv" has been provided to manipulate the privileges database. There are still many things to do (like support in "net rpc vampire") but the working core is here. Feel free to comment/extend on this work. Of course I will deny that any bug may affect this code :-) Simo. This patch adds also my patch about add share command enhancements. (This used to be commit 7a78c3605e203bd8e0d7ae244605f076a5d0b0bc)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/chgpasswd.c2
-rw-r--r--source3/smbd/conn.c8
-rw-r--r--source3/smbd/password.c6
-rw-r--r--source3/smbd/sec_ctx.c27
-rw-r--r--source3/smbd/service.c4
-rw-r--r--source3/smbd/uid.c18
6 files changed, 56 insertions, 9 deletions
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index e3df8a11d0..8e4df1a464 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -991,7 +991,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
if (!push_sec_ctx())
return NT_STATUS_UNSUCCESSFUL;
- set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
+ set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL, NULL);
set_re_uid();
}
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index 9bac0acdb9..0805f8e690 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -249,6 +249,14 @@ void conn_free(connection_struct *conn)
conn->ngroups = 0;
}
+ if (conn->nt_user_token) {
+ delete_nt_token(&(conn->nt_user_token));
+ }
+
+ if (conn->privs) {
+ destroy_privilege(&(conn->privs));
+ }
+
free_namearray(conn->veto_list);
free_namearray(conn->hide_list);
free_namearray(conn->veto_oplock_list);
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 10c6aadb1f..8438f2a593 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -87,6 +87,7 @@ void invalidate_vuid(uint16 vuid)
SAFE_FREE(vuser->groups);
delete_nt_token(&vuser->nt_user_token);
+ destroy_privilege(&vuser->privs);
SAFE_FREE(vuser);
num_validated_vuids--;
}
@@ -234,6 +235,11 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
return UID_FIELD_INVALID;
}
+ if (server_info->privs) {
+ init_privilege(&(vuser->privs));
+ dup_priv_set(vuser->privs, server_info->privs);
+ }
+
/* use this to keep tabs on all our info from the authentication */
vuser->server_info = server_info;
diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c
index 8a85792ead..9244f34394 100644
--- a/source3/smbd/sec_ctx.c
+++ b/source3/smbd/sec_ctx.c
@@ -28,6 +28,7 @@ struct sec_ctx {
int ngroups;
gid_t *groups;
NT_USER_TOKEN *token;
+ PRIVILEGE_SET *privs;
};
/* A stack of security contexts. We include the current context as being
@@ -256,6 +257,10 @@ BOOL push_sec_ctx(void)
(unsigned int)ctx_p->uid, (unsigned int)ctx_p->gid, sec_ctx_stack_ndx ));
ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token);
+ if (! ctx_p->token) {
+ DEBUG(0, ("Out of memory in push_sec_ctx()\n"));
+ return False;
+ }
ctx_p->ngroups = sys_getgroups(0, NULL);
@@ -271,6 +276,14 @@ BOOL push_sec_ctx(void)
ctx_p->groups = NULL;
}
+ init_privilege(&ctx_p->privs);
+ if (! NT_STATUS_IS_OK(dup_priv_set(ctx_p->privs, sec_ctx_stack[sec_ctx_stack_ndx-1].privs))) {
+ DEBUG(0, ("Out of memory in push_sec_ctx()\n"));
+ delete_nt_token(&ctx_p->token);
+ destroy_privilege(&ctx_p->privs);
+ return False;
+ }
+
return True;
}
@@ -278,7 +291,7 @@ BOOL push_sec_ctx(void)
Set the current security context to a given user.
****************************************************************************/
-void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token)
+void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token, PRIVILEGE_SET *privs)
{
struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
@@ -303,9 +316,14 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
smb_panic("DUPLICATE_TOKEN");
delete_nt_token(&ctx_p->token);
+ if (ctx_p->privs)
+ reset_privilege(ctx_p->privs);
+ else
+ init_privilege(&ctx_p->privs);
ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups);
ctx_p->token = dup_nt_token(token);
+ dup_priv_set(ctx_p->privs, privs);
become_id(uid, gid);
@@ -319,6 +337,7 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
current_user.ngroups = ngroups;
current_user.groups = groups;
current_user.nt_user_token = ctx_p->token;
+ current_user.privs = ctx_p->privs;
}
/****************************************************************************
@@ -329,7 +348,7 @@ void set_root_sec_ctx(void)
{
/* May need to worry about supplementary groups at some stage */
- set_sec_ctx(0, 0, 0, NULL, NULL);
+ set_sec_ctx(0, 0, 0, NULL, NULL, NULL);
}
/****************************************************************************
@@ -359,6 +378,7 @@ BOOL pop_sec_ctx(void)
ctx_p->ngroups = 0;
delete_nt_token(&ctx_p->token);
+ destroy_privilege(&ctx_p->privs);
/* Pop back previous user */
@@ -381,6 +401,7 @@ BOOL pop_sec_ctx(void)
current_user.ngroups = prev_ctx_p->ngroups;
current_user.groups = prev_ctx_p->groups;
current_user.nt_user_token = prev_ctx_p->token;
+ current_user.privs = prev_ctx_p->privs;
DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
(unsigned int)geteuid(), (unsigned int)getegid(), sec_ctx_stack_ndx));
@@ -413,6 +434,7 @@ void init_sec_ctx(void)
get_current_groups(ctx_p->gid, &ctx_p->ngroups, &ctx_p->groups);
ctx_p->token = NULL; /* Maps to guest user. */
+ ctx_p->privs = NULL;
/* Initialise current_user global */
@@ -427,4 +449,5 @@ void init_sec_ctx(void)
current_user.conn = NULL;
current_user.vuid = UID_FIELD_INVALID;
current_user.nt_user_token = NULL;
+ current_user.privs = NULL;
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 78b610ae37..caa2872f04 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -371,6 +371,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
string_set(&conn->dirpath,"");
string_set(&conn->user,user);
conn->nt_user_token = NULL;
+ conn->privs = NULL;
conn->read_only = lp_readonly(conn->service);
conn->admin_user = False;
@@ -479,6 +480,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
conn->ngroups, conn->groups,
guest);
+
+ init_privilege(&(conn->privs));
+ pdb_get_privilege_set(conn->nt_user_token, conn->privs);
}
/*
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 3859298055..d43bf301e8 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -44,7 +44,7 @@ BOOL change_to_guest(void)
initgroups(pass->pw_name, pass->pw_gid);
#endif
- set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
+ set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL, NULL);
current_user.conn = NULL;
current_user.vuid = UID_FIELD_INVALID;
@@ -161,8 +161,9 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
gid_t gid;
uid_t uid;
char group_c;
- BOOL must_free_token = False;
+ BOOL must_free_token_priv = False;
NT_USER_TOKEN *token = NULL;
+ PRIVILEGE_SET *privs = NULL;
if (!conn) {
DEBUG(2,("change_to_user: Connection not open\n"));
@@ -195,12 +196,14 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
current_user.groups = conn->groups;
current_user.ngroups = conn->ngroups;
token = conn->nt_user_token;
+ privs = conn->privs;
} else if ((vuser) && check_user_ok(conn, vuser, snum)) {
uid = conn->admin_user ? 0 : vuser->uid;
gid = vuser->gid;
current_user.ngroups = vuser->n_groups;
current_user.groups = vuser->groups;
token = vuser->nt_user_token;
+ privs = vuser->privs;
} else {
DEBUG(2,("change_to_user: Invalid vuid used %d or vuid not permitted access to share.\n",vuid));
return False;
@@ -248,17 +251,20 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
DEBUG(1, ("change_to_user: create_nt_token failed!\n"));
return False;
}
- must_free_token = True;
+ pdb_get_privilege_set(token, privs);
+ must_free_token_priv = True;
}
- set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token);
+ set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token, privs);
/*
* Free the new token (as set_sec_ctx copies it).
*/
- if (must_free_token)
+ if (must_free_token_priv) {
delete_nt_token(&token);
+ destroy_privilege(&privs);
+ }
current_user.conn = conn;
current_user.vuid = vuid;
@@ -299,7 +305,7 @@ BOOL become_authenticated_pipe_user(pipes_struct *p)
return False;
set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid,
- p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token);
+ p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token, p->pipe_user.privs);
return True;
}