smbd: Slightly simplify downgrade_lease()
[samba.git] / source3 / smbd / session.c
index e7e7570f40423a999c0bde57ebd813596b73e582..8b4c660930448224c87de2bc75b3a55c74f31ef6 100644 (file)
  called when a session is created
 ********************************************************************/
 
-bool session_claim(struct smbd_server_connection *sconn, struct user_struct *vuser)
+bool session_claim(struct smbXsrv_session *session)
 {
-       struct server_id pid = messaging_server_id(sconn->msg_ctx);
-       TDB_DATA data;
-       int i = 0;
-       struct sessionid sessionid;
-       fstring keystr;
-       struct db_record *rec;
-       NTSTATUS status;
-       char *raddr;
-
-       vuser->session_keystr = NULL;
+       struct auth_session_info *session_info =
+               session->global->auth_session_info;
+       const char *username;
+       const char *hostname;
+       unsigned int id_num;
+       fstring id_str;
 
        /* don't register sessions for the guest user - its just too
           expensive to go through pam session code for browsing etc */
-       if (security_session_user_level(vuser->session_info, NULL) < SECURITY_USER) {
-               return True;
-       }
-
-       if (!sessionid_init()) {
-               return False;
+       if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
+               return true;
        }
 
-       ZERO_STRUCT(sessionid);
+       id_num = session->global->session_global_id;
 
-       data.dptr = NULL;
-       data.dsize = 0;
-
-       if (lp_utmp()) {
-
-               for (i=1;i<MAX_SESSION_ID;i++) {
-
-                       /*
-                        * This is very inefficient and needs fixing -- vl
-                        */
-
-                       struct server_id sess_pid;
-                       TDB_DATA value;
-
-                       snprintf(keystr, sizeof(keystr), "ID/%d", i);
-
-                       rec = sessionid_fetch_record(NULL, keystr);
-                       if (rec == NULL) {
-                               DEBUG(1, ("Could not lock \"%s\"\n", keystr));
-                               return False;
-                       }
-
-                       value = dbwrap_record_get_value(rec);
-
-                       if (value.dsize != sizeof(sessionid)) {
-                               DEBUG(1, ("Re-using invalid record\n"));
-                               break;
-                       }
-
-                       memcpy(&sess_pid,
-                              ((char *)value.dptr)
-                              + offsetof(struct sessionid, pid),
-                              sizeof(sess_pid));
-
-                       if (!process_exists(sess_pid)) {
-                               DEBUG(5, ("%s has died -- re-using session\n",
-                                         procid_str_static(&sess_pid)));
-                               break;
-                       }
-
-                       TALLOC_FREE(rec);
-               }
-
-               if (i == MAX_SESSION_ID) {
-                       SMB_ASSERT(rec == NULL);
-                       DEBUG(1,("session_claim: out of session IDs "
-                                "(max is %d)\n", MAX_SESSION_ID));
-                       return False;
-               }
-
-               snprintf(sessionid.id_str, sizeof(sessionid.id_str),
-                        SESSION_UTMP_TEMPLATE, i);
-       } else
-       {
-               snprintf(keystr, sizeof(keystr), "ID/%s/%llu",
-                        procid_str_static(&pid),
-                        (unsigned long long)vuser->vuid);
-
-               rec = sessionid_fetch_record(NULL, keystr);
-               if (rec == NULL) {
-                       DEBUG(1, ("Could not lock \"%s\"\n", keystr));
-                       return False;
-               }
-
-               snprintf(sessionid.id_str, sizeof(sessionid.id_str),
-                        SESSION_TEMPLATE, (long unsigned int)getpid(),
-                        (unsigned long long)vuser->vuid);
-       }
-
-       SMB_ASSERT(rec != NULL);
-
-       raddr = tsocket_address_inet_addr_string(sconn->remote_address,
-                                                talloc_tos());
-       if (raddr == NULL) {
-               return false;
-       }
+       snprintf(id_str, sizeof(id_str), "smb/%u", id_num);
 
        /* Make clear that we require the optional unix_token in the source3 code */
-       SMB_ASSERT(vuser->session_info->unix_token);
-
-       fstrcpy(sessionid.username, vuser->session_info->unix_info->unix_name);
-       fstrcpy(sessionid.hostname, sconn->remote_hostname);
-       sessionid.id_num = i;  /* Only valid for utmp sessions */
-       sessionid.pid = pid;
-       sessionid.uid = vuser->session_info->unix_token->uid;
-       sessionid.gid = vuser->session_info->unix_token->gid;
-       fstrcpy(sessionid.remote_machine, get_remote_machine_name());
-       fstrcpy(sessionid.ip_addr_str, raddr);
-       sessionid.connect_start = time(NULL);
-
-       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));
-
-               TALLOC_FREE(rec);
-               return False;
-       }
+       SMB_ASSERT(session_info->unix_token);
 
-       data.dptr = (uint8 *)&sessionid;
-       data.dsize = sizeof(sessionid);
+       username = session_info->unix_info->unix_name;
+       hostname = session->global->channels[0].remote_name;
 
-       status = dbwrap_record_store(rec, data, TDB_REPLACE);
-
-       TALLOC_FREE(rec);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(1,("session_claim: unable to create session id "
-                        "record: %s\n", nt_errstr(status)));
-               return False;
+       if (!smb_pam_claim_session(username, id_str, hostname)) {
+               DEBUG(1,("pam_session rejected the session for %s [%s]\n",
+                               username, id_str));
+               return false;
        }
 
        if (lp_utmp()) {
-               sys_utmp_claim(sessionid.username, sessionid.hostname,
-                              sessionid.id_str, sessionid.id_num);
+               sys_utmp_claim(username, hostname, id_str, id_num);
        }
 
-       vuser->session_keystr = talloc_strdup(vuser, keystr);
-       if (!vuser->session_keystr) {
-               DEBUG(0, ("session_claim:  talloc_strdup() failed for session_keystr\n"));
-               return False;
-       }
-       return True;
+       return true;
 }
 
 /********************************************************************
  called when a session is destroyed
 ********************************************************************/
 
-void session_yield(struct user_struct *vuser)
+void session_yield(struct smbXsrv_session *session)
 {
-       struct sessionid sessionid;
-       struct db_record *rec;
-       TDB_DATA value;
-
-       if (!vuser->session_keystr) {
-               return;
-       }
+       struct auth_session_info *session_info =
+               session->global->auth_session_info;
+       const char *username;
+       const char *hostname;
+       unsigned int id_num;
+       fstring id_str = "";
 
-       rec = sessionid_fetch_record(NULL, vuser->session_keystr);
-       if (rec == NULL) {
-               return;
-       }
+       id_num = session->global->session_global_id;
 
-       value = dbwrap_record_get_value(rec);
+       snprintf(id_str, sizeof(id_str), "smb/%u", id_num);
 
-       if (value.dsize != sizeof(sessionid))
-               return;
+       /* Make clear that we require the optional unix_token in the source3 code */
+       SMB_ASSERT(session_info->unix_token);
 
-       memcpy(&sessionid, value.dptr, sizeof(sessionid));
+       username = session_info->unix_info->unix_name;
+       hostname = session->global->channels[0].remote_name;
 
        if (lp_utmp()) {
-               sys_utmp_yield(sessionid.username, sessionid.hostname, 
-                              sessionid.id_str, sessionid.id_num);
+               sys_utmp_yield(username, hostname, id_str, id_num);
        }
 
-       smb_pam_close_session(sessionid.username, sessionid.id_str,
-                             sessionid.hostname);
-
-       dbwrap_record_delete(rec);
-
-       TALLOC_FREE(rec);
+       smb_pam_close_session(username, id_str, hostname);
 }
 
 /********************************************************************
@@ -235,6 +114,8 @@ void session_yield(struct user_struct *vuser)
 struct session_list {
        TALLOC_CTX *mem_ctx;
        int count;
+       const char *filter_user;
+       const char *filter_machine;
        struct sessionid *sessions;
 };
 
@@ -243,6 +124,25 @@ static int gather_sessioninfo(const char *key, struct sessionid *session,
 {
        struct session_list *sesslist = (struct session_list *)private_data;
 
+       /* filter the session if required */
+
+       if (sesslist->filter_user &&
+           (sesslist->filter_user[0] != '\0') &&
+           !strequal(session->username, sesslist->filter_user)) {
+               return 0;
+       }
+
+       if (sesslist->filter_machine &&
+           (sesslist->filter_machine[0] != '\0') &&
+           !strequal(session->remote_machine,
+                     sesslist->filter_machine)) {
+               return 0;
+       }
+
+       if (!process_exists(session->pid)) {
+               return 0;
+       }
+
        sesslist->sessions = talloc_realloc(
                sesslist->mem_ctx, sesslist->sessions, struct sessionid,
                sesslist->count+1);
@@ -273,6 +173,8 @@ int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list)
 
        sesslist.mem_ctx = mem_ctx;
        sesslist.count = 0;
+       sesslist.filter_user = NULL;
+       sesslist.filter_machine = NULL;
        sesslist.sessions = NULL;
 
        status = sessionid_traverse_read(gather_sessioninfo, (void *) &sesslist);
@@ -286,3 +188,31 @@ int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list)
        *session_list = sesslist.sessions;
        return sesslist.count;
 }
+
+/********************************************************************
+find the sessions that match the given username and machine
+********************************************************************/
+
+int find_sessions(TALLOC_CTX *mem_ctx, const char *username,
+                 const char *machine, struct sessionid **session_list)
+{
+       struct session_list sesslist;
+       NTSTATUS status;
+
+       sesslist.mem_ctx = mem_ctx;
+       sesslist.count = 0;
+       sesslist.filter_user = username;
+       sesslist.filter_machine = machine;
+       sesslist.sessions = NULL;
+
+       status = sessionid_traverse_read(gather_sessioninfo, (void *)&sesslist);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("Session traverse failed: %s\n", nt_errstr(status)));
+               TALLOC_FREE(sesslist.sessions);
+               *session_list = NULL;
+               return 0;
+       }
+
+       *session_list = sesslist.sessions;
+       return sesslist.count;
+}