Unix SMB/CIFS implementation.
uid/user handling
Copyright (C) Tim Potter 2000
-
+
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
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "libcli/security/security_token.h"
+#include "auth.h"
extern struct current_user current_user;
-struct sec_ctx {
- UNIX_USER_TOKEN ut;
- NT_USER_TOKEN *token;
-};
-
-/* A stack of security contexts. We include the current context as being
- the first one, so there is room for another MAX_SEC_CTX_DEPTH more. */
+/****************************************************************************
+ Are two UNIX tokens equal ?
+****************************************************************************/
-static struct sec_ctx sec_ctx_stack[MAX_SEC_CTX_DEPTH + 1];
-static int sec_ctx_stack_ndx;
+bool unix_token_equal(const struct security_unix_token *t1, const struct security_unix_token *t2)
+{
+ if (t1->uid != t2->uid || t1->gid != t2->gid ||
+ t1->ngroups != t2->ngroups) {
+ return false;
+ }
+ if (memcmp(t1->groups, t2->groups,
+ t1->ngroups*sizeof(gid_t)) != 0) {
+ return false;
+ }
+ return true;
+}
/****************************************************************************
Become the specified uid.
****************************************************************************/
-static BOOL become_uid(uid_t uid)
+static bool become_uid(uid_t uid)
{
/* Check for dodgy uid values */
if (uid == (uid_t)-1 ||
((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) {
- static int done;
-
- if (!done) {
+ if (!become_uid_done) {
DEBUG(1,("WARNING: using uid %d is a security risk\n",
(int)uid));
- done = 1;
+ become_uid_done = true;
}
}
Become the specified gid.
****************************************************************************/
-static BOOL become_gid(gid_t gid)
+static bool become_gid(gid_t gid)
{
/* Check for dodgy gid values */
if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) &&
(gid == (gid_t)65535))) {
- static int done;
-
- if (!done) {
+ if (!become_gid_done) {
DEBUG(1,("WARNING: using gid %d is a security risk\n",
(int)gid));
- done = 1;
+ become_gid_done = true;
}
}
-
+
/* Set effective group id */
set_effective_gid(gid);
Become the specified uid and gid.
****************************************************************************/
-static BOOL become_id(uid_t uid, gid_t gid)
+static bool become_id(uid_t uid, gid_t gid)
{
return become_gid(gid) && become_uid(uid);
}
Get the list of current groups.
****************************************************************************/
-static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
+static int get_current_groups(gid_t gid, uint32_t *p_ngroups, gid_t **p_groups)
{
int i;
gid_t grp;
(*p_ngroups) = ngroups;
(*p_groups) = groups;
- DEBUG( 3, ( "get_current_groups: user is in %u groups: ", ngroups));
+ DEBUG( 4, ( "get_current_groups: user is in %u groups: ", ngroups));
for (i = 0; i < ngroups; i++ ) {
- DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
+ DEBUG( 4, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
}
- DEBUG( 3, ( "\n" ) );
+ DEBUG( 4, ( "\n" ) );
return ngroups;
one. User changes are done using the set_sec_ctx() function.
****************************************************************************/
-BOOL push_sec_ctx(void)
+bool push_sec_ctx(void)
{
struct sec_ctx *ctx_p;
ctx_p->ut.uid = geteuid();
ctx_p->ut.gid = getegid();
- DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n",
+ DEBUG(4, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n",
(unsigned int)ctx_p->ut.uid, (unsigned int)ctx_p->ut.gid, sec_ctx_stack_ndx ));
ctx_p->token = dup_nt_token(NULL,
/* Start context switch */
gain_root();
#ifdef HAVE_SETGROUPS
- sys_setgroups(gid, ngroups, groups);
+ if (sys_setgroups(gid, ngroups, groups) != 0 && !non_root_mode()) {
+ smb_panic("sys_setgroups failed");
+ }
#endif
become_id(uid, gid);
/* end context switch */
if (syscall(SYS_initgroups, (ngroups > max) ? max : ngroups,
- groups, uid) == 1) {
+ groups, uid) == -1 && !non_root_mode()) {
DEBUG(0, ("WARNING: failed to set group list "
"(%d groups) for UID %ld: %s\n",
ngroups, uid, strerror(errno)));
+ smb_panic("sys_setgroups failed");
}
become_uid(uid);
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, struct security_token *token)
{
struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
-
+
/* Set the security context */
- DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
+ DEBUG(4, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
(unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx));
- debug_nt_user_token(DBGC_CLASS, 5, token);
+ security_token_debug(DBGC_CLASS, 5, token);
debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups);
/* Change uid, gid and supplementary group list. */
}
TALLOC_FREE(ctx_p->token);
-
+
if (ngroups) {
ctx_p->ut.groups = (gid_t *)memdup(groups,
sizeof(gid_t) * ngroups);
Pop a security context from the stack.
****************************************************************************/
-BOOL pop_sec_ctx(void)
+bool pop_sec_ctx(void)
{
struct sec_ctx *ctx_p;
struct sec_ctx *prev_ctx_p;
current_user.ut.groups = prev_ctx_p->ut.groups;
current_user.nt_user_token = prev_ctx_p->token;
- DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
+ DEBUG(4, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
(unsigned int)geteuid(), (unsigned int)getegid(), sec_ctx_stack_ndx));
return True;