smbd/session.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    session handling for utmp and PAM
00004 
00005    Copyright (C) tridge@samba.org       2001
00006    Copyright (C) abartlet@samba.org     2001
00007    Copyright (C) Gerald (Jerry) Carter  2006   
00008    
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 /* a "session" is claimed when we do a SessionSetupX operation
00025    and is yielded when the corresponding vuid is destroyed.
00026 
00027    sessions are used to populate utmp and PAM session structures
00028 */
00029 
00030 #include "includes.h"
00031 
00032 static TDB_CONTEXT *tdb;
00033 
00034 /********************************************************************
00035 ********************************************************************/
00036 
00037 BOOL session_init(void)
00038 {
00039         if (tdb)
00040                 return True;
00041 
00042         tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
00043                        O_RDWR | O_CREAT, 0644);
00044         if (!tdb) {
00045                 DEBUG(1,("session_init: failed to open sessionid tdb\n"));
00046                 return False;
00047         }
00048 
00049         return True;
00050 }
00051 
00052 /********************************************************************
00053  called when a session is created
00054 ********************************************************************/
00055 
00056 BOOL session_claim(user_struct *vuser)
00057 {
00058         int i = 0;
00059         TDB_DATA data;
00060         struct sockaddr sa;
00061         struct in_addr *client_ip;
00062         struct sessionid sessionid;
00063         uint32 pid = (uint32)sys_getpid();
00064         TDB_DATA key;           
00065         fstring keystr;
00066         char * hostname;
00067         int tdb_store_flag;  /* If using utmp, we do an inital 'lock hold' store,
00068                                 but we don't need this if we are just using the 
00069                                 (unique) pid/vuid combination */
00070 
00071         vuser->session_keystr = NULL;
00072 
00073         /* don't register sessions for the guest user - its just too
00074            expensive to go through pam session code for browsing etc */
00075         if (vuser->guest) {
00076                 return True;
00077         }
00078 
00079         if (!session_init())
00080                 return False;
00081 
00082         ZERO_STRUCT(sessionid);
00083 
00084         data.dptr = NULL;
00085         data.dsize = 0;
00086 
00087         if (lp_utmp()) {
00088                 for (i=1;i<MAX_SESSION_ID;i++) {
00089                         slprintf(keystr, sizeof(keystr)-1, "ID/%d", i);
00090                         key.dptr = keystr;
00091                         key.dsize = strlen(keystr)+1;
00092                         
00093                         if (tdb_store(tdb, key, data, TDB_INSERT) == 0) break;
00094                 }
00095                 
00096                 if (i == MAX_SESSION_ID) {
00097                         DEBUG(1,("session_claim: out of session IDs (max is %d)\n", 
00098                                  MAX_SESSION_ID));
00099                         return False;
00100                 }
00101                 slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_UTMP_TEMPLATE, i);
00102                 tdb_store_flag = TDB_MODIFY;
00103         } else
00104         {
00105                 slprintf(keystr, sizeof(keystr)-1, "ID/%lu/%u", 
00106                          (long unsigned int)sys_getpid(), 
00107                          vuser->vuid);
00108                 slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, 
00109                          SESSION_TEMPLATE, (long unsigned int)sys_getpid(), 
00110                          vuser->vuid);
00111 
00112                 key.dptr = keystr;
00113                 key.dsize = strlen(keystr)+1;
00114                         
00115                 tdb_store_flag = TDB_REPLACE;
00116         }
00117 
00118         /* If 'hostname lookup' == yes, then do the DNS lookup.  This is
00119            needed because utmp and PAM both expect DNS names 
00120            
00121            client_name() handles this case internally.
00122         */
00123 
00124         hostname = client_name();
00125         if (strcmp(hostname, "UNKNOWN") == 0) {
00126                 hostname = client_addr();
00127         }
00128 
00129         fstrcpy(sessionid.username, vuser->user.unix_name);
00130         fstrcpy(sessionid.hostname, hostname);
00131         sessionid.id_num = i;  /* Only valid for utmp sessions */
00132         sessionid.pid = pid;
00133         sessionid.uid = vuser->uid;
00134         sessionid.gid = vuser->gid;
00135         fstrcpy(sessionid.remote_machine, get_remote_machine_name());
00136         fstrcpy(sessionid.ip_addr, client_addr());
00137         sessionid.connect_start = time(NULL);
00138 
00139         client_ip = client_inaddr(&sa);
00140 
00141         if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) {
00142                 DEBUG(1,("pam_session rejected the session for %s [%s]\n",
00143                                 sessionid.username, sessionid.id_str));
00144                 if (tdb_store_flag == TDB_MODIFY) {
00145                         tdb_delete(tdb, key);
00146                 }
00147                 return False;
00148         }
00149 
00150         data.dptr = (char *)&sessionid;
00151         data.dsize = sizeof(sessionid);
00152         if (tdb_store(tdb, key, data, tdb_store_flag) != 0) {
00153                 DEBUG(1,("session_claim: unable to create session id record\n"));
00154                 return False;
00155         }
00156 
00157         if (lp_utmp()) {
00158                 sys_utmp_claim(sessionid.username, sessionid.hostname, 
00159                                client_ip,
00160                                sessionid.id_str, sessionid.id_num);
00161         }
00162 
00163         vuser->session_keystr = SMB_STRDUP(keystr);
00164         if (!vuser->session_keystr) {
00165                 DEBUG(0, ("session_claim:  strdup() failed for session_keystr\n"));
00166                 return False;
00167         }
00168         return True;
00169 }
00170 
00171 /********************************************************************
00172  called when a session is destroyed
00173 ********************************************************************/
00174 
00175 void session_yield(user_struct *vuser)
00176 {
00177         TDB_DATA dbuf;
00178         struct sessionid sessionid;
00179         struct in_addr *client_ip;
00180         TDB_DATA key;
00181 
00182         if (!tdb) return;
00183 
00184         if (!vuser->session_keystr) {
00185                 return;
00186         }
00187 
00188         key.dptr = vuser->session_keystr;
00189         key.dsize = strlen(vuser->session_keystr)+1;
00190 
00191         dbuf = tdb_fetch(tdb, key);
00192 
00193         if (dbuf.dsize != sizeof(sessionid))
00194                 return;
00195 
00196         memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
00197 
00198         client_ip = interpret_addr2(sessionid.ip_addr);
00199 
00200         SAFE_FREE(dbuf.dptr);
00201 
00202         if (lp_utmp()) {
00203                 sys_utmp_yield(sessionid.username, sessionid.hostname, 
00204                                client_ip,
00205                                sessionid.id_str, sessionid.id_num);
00206         }
00207 
00208         smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname);
00209 
00210         tdb_delete(tdb, key);
00211 }
00212 
00213 /********************************************************************
00214 ********************************************************************/
00215 
00216 BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
00217                       void *state)
00218 {
00219         if (!session_init()) {
00220                 DEBUG(3, ("No tdb opened\n"));
00221                 return False;
00222         }
00223 
00224         tdb_traverse(tdb, fn, state);
00225         return True;
00226 }
00227 
00228 /********************************************************************
00229 ********************************************************************/
00230 
00231 struct session_list {
00232         int count;
00233         struct sessionid *sessions;
00234 };
00235 
00236 static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
00237 {
00238         uint32 i;       
00239         struct session_list *sesslist = (struct session_list *) state;
00240         const struct sessionid *current = (const struct sessionid *) dbuf.dptr;
00241 
00242         i = sesslist->count;
00243         
00244         sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1);
00245         if (!sesslist->sessions) {
00246                 sesslist->count = 0;
00247                 return -1;
00248         }
00249 
00250         memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid));
00251         sesslist->count++;
00252 
00253         DEBUG(7,("gather_sessioninfo session from %s@%s\n", 
00254                  current->username, current->remote_machine));
00255 
00256         return 0;
00257 }
00258 
00259 /********************************************************************
00260 ********************************************************************/
00261 
00262 int list_sessions(struct sessionid **session_list)
00263 {
00264         struct session_list sesslist;
00265 
00266         sesslist.count = 0;
00267         sesslist.sessions = NULL;
00268         
00269         if (!session_traverse(gather_sessioninfo, (void *) &sesslist)) {
00270                 DEBUG(3, ("Session traverse failed\n"));
00271                 SAFE_FREE(sesslist.sessions);
00272                 *session_list = NULL;
00273                 return 0;
00274         }
00275 
00276         *session_list = sesslist.sessions;
00277         return sesslist.count;
00278 }

Sambaに対してSat Aug 29 21:23:26 2009に生成されました。  doxygen 1.4.7