diff options
-rw-r--r-- | source4/include/rewrite.h | 13 | ||||
-rw-r--r-- | source4/ntvfs/ipc/vfs_ipc.c | 4 | ||||
-rw-r--r-- | source4/smb_server/password.c | 106 | ||||
-rw-r--r-- | source4/smb_server/reply.c | 2 | ||||
-rw-r--r-- | source4/smb_server/service.c | 11 | ||||
-rw-r--r-- | source4/smb_server/session.c | 4 | ||||
-rw-r--r-- | source4/smb_server/sesssetup.c | 4 | ||||
-rw-r--r-- | source4/smb_server/smb_server.c | 25 | ||||
-rw-r--r-- | source4/smb_server/smb_server.h | 25 |
9 files changed, 90 insertions, 104 deletions
diff --git a/source4/include/rewrite.h b/source4/include/rewrite.h index ee6840abfb..c8587f5e4e 100644 --- a/source4/include/rewrite.h +++ b/source4/include/rewrite.h @@ -246,19 +246,6 @@ struct node_status { #include "rpc_secdes.h" -typedef struct user_struct -{ - struct user_struct *next, *prev; - uint16_t vuid; /* Tag for this entry. */ - - char *session_keystr; /* used by utmp and pam session code. - TDB key string */ - int homes_snum; - - struct auth_session_info *session_info; - -} user_struct; - #include "client.h" /* diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 73b3de314d..2e44b00c6b 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -242,11 +242,11 @@ static NTSTATUS ipc_open_generic(struct smbsrv_request *req, const char *fname, ep_description.info.smb_pipe = p->pipe_name; /* tell the RPC layer the session_info */ - if (req->user_ctx->vuser) { + if (req->session) { /* The session info is refcount-increased in the dcesrv_endpoint_search_connect() function */ - session_info = req->user_ctx->vuser->session_info; + session_info = req->session->session_info; } status = dcesrv_endpoint_search_connect(&req->smb_conn->dcesrv, diff --git a/source4/smb_server/password.c b/source4/smb_server/password.c index 6132e9f84f..e297be6c75 100644 --- a/source4/smb_server/password.c +++ b/source4/smb_server/password.c @@ -26,20 +26,20 @@ check if a uid has been validated, and return an pointer to the user_struct if it has. NULL if not. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ -struct user_struct *get_valid_user_struct(struct smbsrv_connection *smb, uint16_t vuid) +struct smbsrv_session *smbsrv_session_find(struct smbsrv_connection *smb_conn, uint16_t vuid) { - user_struct *usp; + struct smbsrv_session *sess; int count=0; if (vuid == UID_FIELD_INVALID) return NULL; - for (usp=smb->users.validated_users;usp;usp=usp->next,count++) { - if (vuid == usp->vuid) { + for (sess=smb_conn->sessions.session_list; sess; sess=sess->next,count++) { + if (vuid == sess->vuid) { if (count > 10) { - DLIST_PROMOTE(smb->users.validated_users, usp); + DLIST_PROMOTE(smb_conn->sessions.session_list, sess); } - return usp; + return sess; } } @@ -49,38 +49,37 @@ struct user_struct *get_valid_user_struct(struct smbsrv_connection *smb, uint16_ /**************************************************************************** invalidate a uid ****************************************************************************/ -void invalidate_vuid(struct smbsrv_connection *smb, uint16_t vuid) +void smbsrv_invalidate_vuid(struct smbsrv_connection *smb_conn, uint16_t vuid) { - user_struct *vuser = get_valid_user_struct(smb, vuid); + struct smbsrv_session *sess = smbsrv_session_find(smb_conn, vuid); - if (vuser == NULL) + if (sess == NULL) return; - session_yield(vuser); + session_yield(sess); - free_session_info(&vuser->session_info); + free_session_info(&sess->session_info); - DLIST_REMOVE(smb->users.validated_users, vuser); + DLIST_REMOVE(smb_conn->sessions.session_list, sess); /* clear the vuid from the 'cache' on each connection, and from the vuid 'owner' of connections */ /* REWRITE: conn_clear_vuid_cache(smb, vuid); */ - SAFE_FREE(vuser); - smb->users.num_validated_vuids--; + smb_conn->sessions.num_validated_vuids--; } /**************************************************************************** invalidate all vuid entries for this process ****************************************************************************/ -void invalidate_all_vuids(struct smbsrv_connection *smb) +void smbsrv_invalidate_all_vuids(struct smbsrv_connection *smb_conn) { - user_struct *usp, *next=NULL; + struct smbsrv_session *sess,*next=NULL; - for (usp=smb->users.validated_users;usp;usp=next) { - next = usp->next; + for (sess=smb_conn->sessions.session_list; sess; sess=next) { + next = sess->next; - invalidate_vuid(smb, usp->vuid); + smbsrv_invalidate_vuid(smb_conn, sess->vuid); } } @@ -98,53 +97,60 @@ void invalidate_all_vuids(struct smbsrv_connection *smb) * */ -int register_vuid(struct smbsrv_connection *smb, - struct auth_session_info *session_info, - const char *smb_name) +uint16_t smbsrv_register_session(struct smbsrv_connection *smb_conn, + struct auth_session_info *session_info, + struct gensec_security *gensec_ctx) { - user_struct *vuser = NULL; + struct smbsrv_session *sess = NULL; - /* Ensure no vuid gets registered in share level security. */ - if(lp_security() == SEC_SHARE) + sess = talloc_p(smb_conn->mem_ctx, struct smbsrv_session); + if(sess == NULL) { + DEBUG(0,("talloc_p(smb_conn->mem_ctx, struct smbsrv_session) failed\n")); return UID_FIELD_INVALID; + } - /* Limit allowed vuids to 16bits - VUID_OFFSET. */ - if (smb->users.num_validated_vuids >= 0xFFFF-VUID_OFFSET) - return UID_FIELD_INVALID; + ZERO_STRUCTP(sess); + sess->vuid = UID_FIELD_INVALID; - if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) { - DEBUG(0,("Failed to malloc users struct!\n")); - return UID_FIELD_INVALID; - } + /* Ensure no vuid gets registered in share level security. */ + /* TODO: replace lp_security with a flag in smbsrv_connection */ + if(lp_security() == SEC_SHARE) + return sess->vuid; - ZERO_STRUCTP(vuser); + /* Limit allowed vuids to 16bits - VUID_OFFSET. */ + if (smb_conn->sessions.num_validated_vuids >= 0xFFFF-VUID_OFFSET) + return sess->vuid; /* Allocate a free vuid. Yes this is a linear search... :-) */ - while (get_valid_user_struct(smb, smb->users.next_vuid) != NULL ) { - smb->users.next_vuid++; + while (smbsrv_session_find(smb_conn, smb_conn->sessions.next_vuid) != NULL ) { + smb_conn->sessions.next_vuid++; /* Check for vuid wrap. */ - if (smb->users.next_vuid == UID_FIELD_INVALID) - smb->users.next_vuid = VUID_OFFSET; + if (smb_conn->sessions.next_vuid == UID_FIELD_INVALID) + smb_conn->sessions.next_vuid = VUID_OFFSET; } DEBUG(10,("register_vuid: allocated vuid = %u\n", - (uint_t)smb->users.next_vuid)); + (uint_t)smb_conn->sessions.next_vuid)); - vuser->vuid = smb->users.next_vuid; + sess->vuid = smb_conn->sessions.next_vuid; + smb_conn->sessions.next_vuid++; + smb_conn->sessions.num_validated_vuids++; /* use this to keep tabs on all our info from the authentication */ - vuser->session_info = session_info; - - smb->users.next_vuid++; - smb->users.num_validated_vuids++; - - DLIST_ADD(smb->users.validated_users, vuser); - - if (!session_claim(smb, vuser)) { - DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid)); - invalidate_vuid(smb, vuser->vuid); + sess->session_info = session_info; + sess->gensec_ctx = gensec_ctx; + + sess->smb_conn = smb_conn; + DLIST_ADD(smb_conn->sessions.session_list, sess); + + /* we only need to do session_claim() when the session_setup is complete + * for spnego session_info is NULL the first time + */ + if (session_info && !session_claim(sess)) { + DEBUG(1,("Failed to claim session for vuid=%d\n", sess->vuid)); + smbsrv_invalidate_vuid(smb_conn, sess->vuid); return UID_FIELD_INVALID; } - return vuser->vuid; + return sess->vuid; } diff --git a/source4/smb_server/reply.c b/source4/smb_server/reply.c index bc79892204..e705181ef2 100644 --- a/source4/smb_server/reply.c +++ b/source4/smb_server/reply.c @@ -2112,7 +2112,7 @@ void reply_ulogoffX(struct smbsrv_request *req) DEBUG(0,("REWRITE: not closing user files\n")); } - invalidate_vuid(req->smb_conn, vuid); + smbsrv_invalidate_vuid(req->smb_conn, vuid); req_setup_reply(req, 2, 0); diff --git a/source4/smb_server/service.c b/source4/smb_server/service.c index 0a06e2edfa..9eb28ff079 100644 --- a/source4/smb_server/service.c +++ b/source4/smb_server/service.c @@ -277,17 +277,22 @@ void close_cnum(struct smbsrv_tcon *tcon) NTSTATUS tcon_backend(struct smbsrv_request *req, union smb_tcon *con) { NTSTATUS status; + uint16_t vuid = UID_FIELD_INVALID; /* can only do bare tcon in share level security */ - if (req->user_ctx == NULL && lp_security() != SEC_SHARE) { + if (req->session == NULL && lp_security() != SEC_SHARE) { return NT_STATUS_ACCESS_DENIED; } + if (req->session) { + vuid = req->session->vuid; + } + if (con->generic.level == RAW_TCON_TCON) { DATA_BLOB password; password = data_blob(con->tcon.in.password, strlen(con->tcon.in.password) + 1); - status = make_connection(req, con->tcon.in.service, password, con->tcon.in.dev, req->user_ctx->vuid); + status = make_connection(req, con->tcon.in.service, password, con->tcon.in.dev, vuid); if (!NT_STATUS_IS_OK(status)) { return status; @@ -300,7 +305,7 @@ NTSTATUS tcon_backend(struct smbsrv_request *req, union smb_tcon *con) } status = make_connection(req, con->tconx.in.path, con->tconx.in.password, - con->tconx.in.device, req->user_ctx->vuid); + con->tconx.in.device, vuid); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/smb_server/session.c b/source4/smb_server/session.c index 8df12faff9..1567484a49 100644 --- a/source4/smb_server/session.c +++ b/source4/smb_server/session.c @@ -28,14 +28,14 @@ #include "includes.h" /* called when a session is created */ -BOOL session_claim(struct smbsrv_connection *smb_ctx, user_struct *vuser) +BOOL session_claim(struct smbsrv_session *sess) { DEBUG(0,("rewrite: Not doing session claim\n")); return True; } /* called when a session is destroyed */ -void session_yield(user_struct *vuser) +void session_yield(struct smbsrv_session *sess) { DEBUG(0,("rewrite: Not doing session yield\n")); } diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index d03e613d48..44a8840d00 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -73,7 +73,7 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s } sess->old.out.action = 0; - sess->old.out.vuid = register_vuid(req->smb_conn, session_info, sess->old.in.user); + sess->old.out.vuid = smbsrv_register_session(req->smb_conn, session_info, NULL); if (sess->old.out.vuid == UID_FIELD_INVALID) { return NT_STATUS_ACCESS_DENIED; } @@ -124,7 +124,7 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s } sess->nt1.out.action = 0; - sess->nt1.out.vuid = register_vuid(req->smb_conn, session_info, sess->nt1.in.user); + sess->nt1.out.vuid = smbsrv_register_session(req->smb_conn, session_info, NULL); if (sess->nt1.out.vuid == UID_FIELD_INVALID) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 351d9ddf4e..94bf6302c1 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -114,21 +114,6 @@ static struct smbsrv_request *receive_smb_request(struct smbsrv_connection *smb_ } /* - setup the user_ctx element of a request -*/ -static void setup_user_context(struct smbsrv_request *req) -{ - struct smbsrv_user *user_ctx; - - user_ctx = talloc(req->mem_ctx, sizeof(*user_ctx)); - user_ctx->vuid = SVAL(req->in.hdr, HDR_UID); - user_ctx->vuser = get_valid_user_struct(req->smb_conn, user_ctx->vuid); - - req->user_ctx = user_ctx; -} - - -/* These flags determine some of the permissions required to do an operation Note that I don't set NEED_WRITE on some write operations because they @@ -459,13 +444,13 @@ static void switch_message(int type, struct smbsrv_request *req) req->tcon = conn_find(smb_conn, SVAL(req->in.hdr,HDR_TID)); /* setup the user context for this request */ - setup_user_context(req); + req->session = smbsrv_session_find(req->smb_conn, session_tag); /* Ensure this value is replaced in the incoming packet. */ SSVAL(req->in.hdr,HDR_UID,session_tag); - if (req->user_ctx) { - req->user_ctx->vuid = session_tag; + if (req->session) { + req->session->vuid = session_tag; } DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), smb_conn->connection->service->model_ops->get_id(req))); @@ -481,7 +466,7 @@ static void switch_message(int type, struct smbsrv_request *req) } /* see if the vuid is valid */ - if ((flags & AS_USER) && !req->user_ctx->vuser) { + if ((flags & AS_USER) && !req->session) { if (!(flags & AS_GUEST)) { req_reply_error(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); return; @@ -859,7 +844,7 @@ void smbsrv_accept(struct server_connection *conn) smb_conn->negotiate.zone_offset = get_time_zone(time(NULL)); - smb_conn->users.next_vuid = VUID_OFFSET; + smb_conn->sessions.next_vuid = VUID_OFFSET; conn_init(smb_conn); diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index e7b0ecfb02..2eb87f09a3 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -29,14 +29,20 @@ */ /* the current user context for a request */ -struct smbsrv_user { +struct smbsrv_session { + struct smbsrv_session *prev, *next; + + struct smbsrv_connection *smb_conn; + /* the vuid is used to specify the security context for this request. Note that this may not be the same vuid as we received on the wire (for example, for share mode or guest access) */ uint16_t vuid; - struct user_struct *vuser; + struct gensec_security *gensec_ctx; + + struct auth_session_info *session_info; }; @@ -89,8 +95,8 @@ struct smbsrv_request { /* conn is only set for operations that have a valid TID */ struct smbsrv_tcon *tcon; - /* the user context is derived from the vuid plus smb.conf options */ - struct smbsrv_user *user_ctx; + /* the session context is derived from the vuid */ + struct smbsrv_session *session; /* a set of flags to control usage of the request. See REQ_CONTROL_* */ unsigned control_flags; @@ -295,14 +301,11 @@ struct smbsrv_connection { /* context associated with currently valid session setups */ struct { - /* users from session setup */ - char *session_users; /* was a pstring */ - - /* this holds info on user ids that are already validated for this VC */ - struct user_struct *validated_users; - int next_vuid; /* initialise to VUID_OFFSET */ + /* this holds info on session vuids that are already validated for this VC */ + struct smbsrv_session *session_list; + uint16_t next_vuid; /* initialise to VUID_OFFSET */ int num_validated_vuids; - } users; + } sessions; /* this holds long term state specific to the printing subsystem */ struct { |