/**************************************************************************** close a cnum ****************************************************************************/ void close_cnum(connection_struct *conn, uint16 vuid) { DirCacheFlush(SNUM(conn)); unbecome_user(); DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n", remote_machine,conn->client_address, lp_servicename(SNUM(conn)))); yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); if (lp_status(SNUM(conn))) yield_connection(conn,"STATUS.",MAXSTATUS); file_close_conn(conn); dptr_closecnum(conn); /* execute any "postexec = " line */ if (*lp_postexec(SNUM(conn)) && become_user(conn, vuid)) { pstring cmd; pstrcpy(cmd,lp_postexec(SNUM(conn))); standard_sub(conn,cmd); smbrun(cmd,NULL,False); unbecome_user(); } unbecome_user(); /* execute any "root postexec = " line */ if (*lp_rootpostexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpostexec(SNUM(conn))); standard_sub(conn,cmd); smbrun(cmd,NULL,False); } conn_free(conn); }
int main(int argc, char *argv[]) { FILE *f; pstring fname; int uid, c; static pstring servicesf = CONFIGFILE; extern char *optarg; int verbose = 0, brief =0; BOOL processes_only=False; int last_pid=0; struct session_record *ptr; TimeInit(); setup_logging(argv[0],True); charset_initialise(); DEBUGLEVEL = 0; dbf = fopen("/dev/null","w"); if (getuid() != geteuid()) { printf("smbstatus should not be run setuid\n"); return(1); } while ((c = getopt(argc, argv, "pds:u:b")) != EOF) { switch (c) { case 'b': brief = 1; break; case 'd': verbose = 1; break; case 'p': processes_only = 1; break; case 's': pstrcpy(servicesf, optarg); break; case 'u': /* added by OH */ Ucrit_addUsername(optarg); /* added by OH */ break; default: fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */ return (-1); } } get_myname(myhostname, NULL); if (!lp_load(servicesf,False)) { fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); return (-1); } if (verbose) { printf("using configfile = %s\n", servicesf); printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL"); } pstrcpy(fname,lp_lockdir()); standard_sub_basic(fname); trim_string(fname,"","/"); pstrcat(fname,"/STATUS..LCK"); f = fopen(fname,"r"); if (!f) { printf("Couldn't open status file %s\n",fname); if (!lp_status(-1)) printf("You need to have status=yes in your smb config file\n"); return(0); } else if (verbose) { printf("Opened status file %s\n", fname); } uid = getuid(); if (!processes_only) { printf("\nSamba version %s\n",VERSION); if (brief) { printf("PID Username Machine Time logged in\n"); printf("-------------------------------------------------------------------\n"); } else { printf("Service uid gid pid machine\n"); printf("----------------------------------------------\n"); } } while (!feof(f)) { if (fread(&crec,sizeof(crec),1,f) != 1) break; if ( crec.magic == 0x280267 && process_exists(crec.pid) && Ucrit_checkUsername(uidtoname(crec.uid)) /* added by OH */ ) { if (brief) { ptr=srecs; while (ptr!=NULL) { if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0)) { if (ptr->start > crec.start) ptr->start=crec.start; break; } ptr=ptr->next; } if (ptr==NULL) { ptr=(struct session_record *) malloc(sizeof(struct session_record)); ptr->uid=crec.uid; ptr->pid=crec.pid; ptr->start=crec.start; strncpy(ptr->machine,crec.machine,30); ptr->machine[30]='\0'; ptr->next=srecs; srecs=ptr; } } else { Ucrit_addPid(crec.pid); /* added by OH */ if (processes_only) { if (last_pid != crec.pid) printf("%d\n",crec.pid); last_pid = crec.pid; /* XXXX we can still get repeats, have to add a sort at some time */ } else printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s", crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid, crec.machine,crec.addr, asctime(LocalTime(&crec.start))); } } } fclose(f); if (processes_only) exit(0); if (brief) { ptr=srecs; while (ptr!=NULL) { printf("%-8d%-10.10s%-30.30s%s",ptr->pid,uidtoname(ptr->uid),ptr->machine,asctime(LocalTime(&(ptr->start)))); ptr=ptr->next; } printf("\n"); exit(0); } printf("\n"); locking_init(1); if (share_mode_forall(print_share_mode) <= 0) printf("No locked files\n"); printf("\n"); share_status(stdout); locking_end(); return (0); }
/**************************************************************************** make a connection to a service ****************************************************************************/ connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode) { int snum; struct passwd *pass = NULL; BOOL guest = False; BOOL force = False; extern int Client; connection_struct *conn; int ret; strlower(service); snum = find_service(service); if (snum < 0) { extern int Client; if (strequal(service,"IPC$")) { DEBUG(3,("refusing IPC connection\n")); *ecode = ERRnoipc; return NULL; } DEBUG(0,("%s (%s) couldn't find service %s\n", remote_machine, client_addr(Client), service)); *ecode = ERRinvnetname; return NULL; } if (strequal(service,HOMES_NAME)) { if (*user && Get_Pwnam(user,True)) { fstring dos_username; fstrcpy(dos_username, user); unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password, pwlen,dev,vuid,ecode)); } if(lp_security() != SEC_SHARE) { if (validated_username(vuid)) { fstring dos_username; fstrcpy(user,validated_username(vuid)); fstrcpy(dos_username, user); unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } else { /* Security = share. Try with sesssetup_user * as the username. */ if(*sesssetup_user) { fstring dos_username; fstrcpy(user,sesssetup_user); fstrcpy(dos_username, user); unix_to_dos(dos_username, True); return(make_connection(dos_username,user,password,pwlen,dev,vuid,ecode)); } } } if (!lp_snum_ok(snum) || !check_access(Client, lp_hostsallow(snum), lp_hostsdeny(snum))) { *ecode = ERRaccess; return NULL; } /* you can only connect to the IPC$ service as an ipc device */ if (strequal(service,"IPC$")) pstrcpy(dev,"IPC"); if (*dev == '?' || !*dev) { if (lp_print_ok(snum)) { pstrcpy(dev,"LPT1:"); } else { pstrcpy(dev,"A:"); } } /* if the request is as a printer and you can't print then refuse */ strupper(dev); if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { DEBUG(1,("Attempt to connect to non-printer as a printer\n")); *ecode = ERRinvdevice; return NULL; } /* lowercase the user name */ strlower(user); /* add it as a possible user name */ add_session_user(service); /* shall we let them in? */ if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) { DEBUG( 2, ( "Invalid username/password for %s\n", service ) ); *ecode = ERRbadpw; return NULL; } conn = conn_new(); if (!conn) { DEBUG(0,("Couldn't find free connection.\n")); *ecode = ERRnoresource; conn_free(conn); return NULL; } /* find out some info about the user */ pass = Get_Pwnam(user,True); if (pass == NULL) { DEBUG(0,( "Couldn't find account %s\n",user)); *ecode = ERRbaduid; conn_free(conn); return NULL; } conn->read_only = lp_readonly(snum); { pstring list; StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); pstring_sub(list,"%S",service); if (user_in_list(user,list)) conn->read_only = True; StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); pstring_sub(list,"%S",service); if (user_in_list(user,list)) conn->read_only = False; } /* admin user check */ /* JRA - original code denied admin user if the share was marked read_only. Changed as I don't think this is needed, but old code left in case there is a problem here. */ if (user_in_list(user,lp_admin_users(snum)) #if 0 && !conn->read_only #endif ) { conn->admin_user = True; DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); } else { conn->admin_user = False; } conn->force_user = force; conn->vuid = vuid; conn->uid = pass->pw_uid; conn->gid = pass->pw_gid; safe_strcpy(conn->client_address, client_addr(Client), sizeof(conn->client_address)-1); conn->num_files_open = 0; conn->lastused = time(NULL); conn->service = snum; conn->used = True; conn->printer = (strncmp(dev,"LPT",3) == 0); conn->ipc = (strncmp(dev,"IPC",3) == 0); conn->dirptr = NULL; conn->veto_list = NULL; conn->hide_list = NULL; conn->veto_oplock_list = NULL; string_set(&conn->dirpath,""); string_set(&conn->user,user); /* * If force user is true, then store the * given userid and also the primary groupid * of the user we're forcing. */ if (*lp_force_user(snum)) { struct passwd *pass2; pstring fuser; pstrcpy(fuser,lp_force_user(snum)); /* Allow %S to be used by force user. */ pstring_sub(fuser,"%S",service); pass2 = (struct passwd *)Get_Pwnam(fuser,True); if (pass2) { conn->uid = pass2->pw_uid; conn->gid = pass2->pw_gid; string_set(&conn->user,fuser); fstrcpy(user,fuser); conn->force_user = True; DEBUG(3,("Forced user %s\n",fuser)); } else { DEBUG(1,("Couldn't find user %s\n",fuser)); } } #ifdef HAVE_GETGRNAM /* * If force group is true, then override * any groupid stored for the connecting user. */ if (*lp_force_group(snum)) { struct group *gptr; pstring gname; pstring tmp_gname; BOOL user_must_be_member = False; StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1); if (tmp_gname[0] == '+') { user_must_be_member = True; StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2); } else { StrnCpy(gname,tmp_gname,sizeof(pstring)-1); } /* default service may be a group name */ pstring_sub(gname,"%S",service); gptr = (struct group *)getgrnam(gname); if (gptr) { /* * If the user has been forced and the forced group starts * with a '+', then we only set the group to be the forced * group if the forced user is a member of that group. * Otherwise, the meaning of the '+' would be ignored. */ if (conn->force_user && user_must_be_member) { int i; for (i = 0; gptr->gr_mem[i] != NULL; i++) { if (strcmp(user,gptr->gr_mem[i]) == 0) { conn->gid = gptr->gr_gid; DEBUG(3,("Forced group %s for member %s\n",gname,user)); break; } } } else { conn->gid = gptr->gr_gid; DEBUG(3,("Forced group %s\n",gname)); } } else { DEBUG(1,("Couldn't find group %s\n",gname)); } } #endif /* HAVE_GETGRNAM */ { pstring s; pstrcpy(s,lp_pathname(snum)); standard_sub(conn,s); string_set(&conn->connectpath,s); DEBUG(3,("Connect path is %s\n",s)); } /* groups stuff added by ih */ conn->ngroups = 0; conn->groups = NULL; if (!IS_IPC(conn)) { /* Find all the groups this uid is in and store them. Used by become_user() */ setup_groups(conn->user,conn->uid,conn->gid, &conn->ngroups,&conn->groups); /* check number of connections */ if (!claim_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn)), False)) { DEBUG(1,("too many connections - rejected\n")); *ecode = ERRnoresource; conn_free(conn); return NULL; } if (lp_status(SNUM(conn))) claim_connection(conn,"STATUS.", MAXSTATUS,False); } /* IS_IPC */ /* execute any "root preexec = " line */ if (*lp_rootpreexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_rootpreexec(SNUM(conn))); standard_sub(conn,cmd); DEBUG(5,("cmd=%s\n",cmd)); ret = smbrun(cmd,NULL,False); if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); conn_free(conn); *ecode = ERRsrverror; return NULL; } } if (!become_user(conn, conn->vuid)) { DEBUG(0,("Can't become connected user!\n")); if (!IS_IPC(conn)) { yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); if (lp_status(SNUM(conn))) { yield_connection(conn,"STATUS.",MAXSTATUS); } } conn_free(conn); *ecode = ERRbadpw; return NULL; } if (dos_ChDir(conn->connectpath) != 0) { DEBUG(0,("Can't change directory to %s (%s)\n", conn->connectpath,strerror(errno))); unbecome_user(); if (!IS_IPC(conn)) { yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn))); if (lp_status(SNUM(conn))) yield_connection(conn,"STATUS.",MAXSTATUS); } conn_free(conn); *ecode = ERRinvnetname; return NULL; } string_set(&conn->origpath,conn->connectpath); #if SOFTLINK_OPTIMISATION /* resolve any soft links early */ { pstring s; pstrcpy(s,conn->connectpath); dos_GetWd(s); string_set(&conn->connectpath,s); dos_ChDir(conn->connectpath); } #endif add_session_user(user); /* execute any "preexec = " line */ if (*lp_preexec(SNUM(conn))) { pstring cmd; pstrcpy(cmd,lp_preexec(SNUM(conn))); standard_sub(conn,cmd); ret = smbrun(cmd,NULL,False); if (ret != 0 && lp_preexec_close(SNUM(conn))) { DEBUG(1,("preexec gave %d - failing connection\n", ret)); conn_free(conn); *ecode = ERRsrverror; return NULL; } } /* * Print out the 'connected as' stuff here as we need * to know the effective uid and gid we will be using. */ if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { dbgtext( "%s (%s) ", remote_machine, conn->client_address ); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); dbgtext( "as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); dbgtext( "(pid %d)\n", (int)getpid() ); } /* we've finished with the sensitive stuff */ unbecome_user(); /* Add veto/hide lists */ if (!IS_IPC(conn) && !IS_PRINT(conn)) { set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn))); set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn))); set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn))); } return(conn); }
/* show the current server status */ void status_page(void) { const char *v; int autorefresh=0; int refresh_interval=30; TDB_CONTEXT *tdb; smbd_pid = pidfile_pid("smbd"); if (cgi_variable("smbd_restart")) { stop_smbd(); start_smbd(); } if (cgi_variable("smbd_start")) { start_smbd(); } if (cgi_variable("smbd_stop")) { stop_smbd(); } if (cgi_variable("nmbd_restart")) { stop_nmbd(); start_nmbd(); } if (cgi_variable("nmbd_start")) { start_nmbd(); } if (cgi_variable("nmbd_stop")) { stop_nmbd(); } if (cgi_variable("autorefresh")) { autorefresh = 1; } else if (cgi_variable("norefresh")) { autorefresh = 0; } else if (cgi_variable("refresh")) { autorefresh = 1; } if ((v=cgi_variable("refresh_interval"))) { refresh_interval = atoi(v); } if (cgi_variable("show_client_in_col_1")) { PID_or_Machine = 1; } tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); if (tdb) tdb_traverse(tdb, traverse_fn1, NULL); initPid2Machine (); printf("<H2>Server Status</H2>\n"); printf("<FORM method=post>\n"); if (!autorefresh) { printf("<input type=submit value=\"Auto Refresh\" name=autorefresh>\n"); printf("<br>Refresh Interval: "); printf("<input type=text size=2 name=\"refresh_interval\" value=%d>\n", refresh_interval); } else { printf("<input type=submit value=\"Stop Refreshing\" name=norefresh>\n"); printf("<br>Refresh Interval: %d\n", refresh_interval); printf("<input type=hidden name=refresh value=1>\n"); } printf("<p>\n"); if (!tdb) { /* open failure either means no connections have been made or status=no */ if (!lp_status(-1)) printf("You need to have status=yes in your smb config file\n"); } printf("<table>\n"); printf("<tr><td>version:</td><td>%s</td></tr>",VERSION); fflush(stdout); printf("<tr><td>smbd:</td><td>%srunning</td>\n",smbd_running()?"":"not "); if (geteuid() == 0) { if (smbd_running()) { printf("<td><input type=submit name=\"smbd_stop\" value=\"Stop smbd\"></td>\n"); } else { printf("<td><input type=submit name=\"smbd_start\" value=\"Start smbd\"></td>\n"); } printf("<td><input type=submit name=\"smbd_restart\" value=\"Restart smbd\"></td>\n"); } printf("</tr>\n"); fflush(stdout); printf("<tr><td>nmbd:</td><td>%srunning</td>\n",nmbd_running()?"":"not "); if (geteuid() == 0) { if (nmbd_running()) { printf("<td><input type=submit name=\"nmbd_stop\" value=\"Stop nmbd\"></td>\n"); } else { printf("<td><input type=submit name=\"nmbd_start\" value=\"Start nmbd\"></td>\n"); } printf("<td><input type=submit name=\"nmbd_restart\" value=\"Restart nmbd\"></td>\n"); } printf("</tr>\n"); printf("</table>\n"); fflush(stdout); printf("<p><h3>Active Connections</h3>\n"); printf("<table border=1>\n"); printf("<tr><th>PID</th><th>Client</th><th>IP address</th><th>Date</th>\n"); if (geteuid() == 0) { printf("<th>Kill</th>\n"); } printf("</tr>\n"); if (tdb) tdb_traverse(tdb, traverse_fn2, NULL); printf("</table><p>\n"); printf("<p><h3>Active Shares</h3>\n"); printf("<table border=1>\n"); printf("<tr><th>Share</th><th>User</th><th>Group</th><th>PID</th><th>Client</th><th>Date</th></tr>\n\n"); if (tdb) tdb_traverse(tdb, traverse_fn3, NULL); printf("</table><p>\n"); printf("<h3>Open Files</h3>\n"); printf("<table border=1>\n"); printf("<tr><th>%s</th><th>Sharing</th><th>R/W</th><th>Oplock</th><th>File</th><th>Date</th></tr>\n", PID_or_Machine ? "Client" : "PID"); locking_init(1); share_mode_forall(print_share_mode); locking_end(); printf("</table>\n"); if (tdb) tdb_close(tdb); printf("<br><input type=submit name=\"show_client_in_col_1\" value=\"Show Client in col 1\">\n"); printf("<input type=submit name=\"show_pid_in_col_1\" value=\"Show PID in col 1\">\n"); printf("</FORM>\n"); if (autorefresh) { /* this little JavaScript allows for automatic refresh of the page. There are other methods but this seems to be the best alternative */ printf("<script language=\"JavaScript\">\n"); printf("<!--\nsetTimeout('window.location.replace(\"%s/status?refresh_interval=%d&refresh=1\")', %d)\n", cgi_baseurl(), refresh_interval, refresh_interval*1000); printf("//-->\n</script>\n"); } }