diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/Makefile.in | 1 | ||||
-rw-r--r-- | source3/include/proto.h | 6 | ||||
-rw-r--r-- | source3/include/smb.h | 3 | ||||
-rw-r--r-- | source3/include/vagent.h | 51 | ||||
-rw-r--r-- | source3/lib/vagent.c | 242 | ||||
-rw-r--r-- | source3/utils/smb-agent.c | 253 |
6 files changed, 340 insertions, 216 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index cb102e0607..6984baf7c3 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -113,6 +113,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \ lib/util_file.o mem_man/mem_man.o \ lib/util_sock.o lib/unix_sec_ctxt.o \ lib/util_array.o \ + lib/vagent.o \ lib/util_hnd.o UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \ diff --git a/source3/include/proto.h b/source3/include/proto.h index 24dfd6ed1a..5e423e3726 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -138,6 +138,12 @@ BOOL allow_access(char *deny_list,char *allow_list, char *cname,char *caddr); BOOL check_access(int sock, char *allow_list, char *deny_list); +/*The following definitions come from lib/agent.c */ + +void init_sock_redir(struct vagent_ops*va); +void free_sock_redir(struct vagent_ops*va); +void start_agent(struct vagent_ops *va); + /*The following definitions come from lib/bitmap.c */ struct bitmap *bitmap_allocate(int n); diff --git a/source3/include/smb.h b/source3/include/smb.h index 8adfa5e690..d4d2f6712a 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -550,6 +550,9 @@ typedef struct #include "vfs.h" + +#include "vagent.h" + typedef struct connection_struct { struct connection_struct *next, *prev; diff --git a/source3/include/vagent.h b/source3/include/vagent.h new file mode 100644 index 0000000000..19bb976635 --- /dev/null +++ b/source3/include/vagent.h @@ -0,0 +1,51 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Vagent structures and parameters + Copyright (C) Luke Kenneth Casson Leighton 1999 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _VAGENT_H +#define _VAGENT_H + +/* Vagent operations structure */ + +struct sock_redir +{ + int c; + int s; + int c_id; + int s_id; + void *n; +}; + +struct vagent_ops +{ + void (*free_sock)(void* sock); + int (*get_agent_sock)(void* id); + + BOOL (*process_cli_sock)(struct sock_redir **socks, uint32 num_socks, + struct sock_redir *sock); + BOOL (*process_srv_sock)(struct sock_redir **socks, uint32 num_socks, + int fd); + + void* id; + struct sock_redir **socks; + uint32 num_socks; +}; + +#endif /* _VAGENT_H */ diff --git a/source3/lib/vagent.c b/source3/lib/vagent.c new file mode 100644 index 0000000000..96df03e2f3 --- /dev/null +++ b/source3/lib/vagent.c @@ -0,0 +1,242 @@ +/* + Unix SMB/Netbios implementation. + Version 2 + SMB agent/socket plugin + Copyright (C) Andrew Tridgell 1999 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "smb.h" + +extern int DEBUGLEVEL; + + +/**************************************************************************** +terminate socket connection +****************************************************************************/ +static void sock_redir_free(struct vagent_ops *va, struct sock_redir *sock) +{ + if (sock->c != -1) + { + close(sock->c); + sock->c = -1; + } + if (sock->n != NULL) + { + va->free_sock(sock->n); + sock->n = NULL; + } + free(sock); +} + +/**************************************************************************** +free a sockent array +****************************************************************************/ +static void free_sock_array(struct vagent_ops*va) +{ + void(*fn)(void*) = (void(*)(void*))&va->free_sock; + free_void_array(va->num_socks, (void**)va->socks, *fn); +} + +/**************************************************************************** +add a sockent state to the array +****************************************************************************/ +static struct sock_redir* add_sock_to_array(uint32 *len, + struct sock_redir ***array, + struct sock_redir *sock) +{ + int i; + for (i = 0; i < (*len); i++) + { + if ((*array)[i] == NULL) + { + (*array)[i] = sock; + return sock; + } + } + + return (struct sock_redir*)add_item_to_array(len, + (void***)array, (void*)sock); + +} + +/**************************************************************************** +initiate sockent array +****************************************************************************/ +void init_sock_redir(struct vagent_ops*va) +{ + va->socks = NULL; + va->num_socks = 0; +} + +/**************************************************************************** +terminate sockent array +****************************************************************************/ +void free_sock_redir(struct vagent_ops*va) +{ + free_sock_array(va); + init_sock_redir(va); +} + +/**************************************************************************** +create a new sockent state from user credentials +****************************************************************************/ +static struct sock_redir *sock_redir_get(struct vagent_ops *va, int fd) +{ + struct sock_redir *sock = (struct sock_redir*)malloc(sizeof(*sock)); + + if (sock == NULL) + { + return NULL; + } + + ZERO_STRUCTP(sock); + + sock->c = fd; + sock->n = NULL; + + DEBUG(10,("sock_redir_get:\tfd:\t%d\n", fd)); + + return sock; +} +/**************************************************************************** +init sock state +****************************************************************************/ +static void sock_add(struct vagent_ops *va, int fd) +{ + struct sock_redir *sock; + sock = sock_redir_get(va, fd); + if (sock != NULL) + { + add_sock_to_array(&va->num_socks, &va->socks, sock); + } +} + +/**************************************************************************** +delete a sockent state +****************************************************************************/ +static BOOL sock_del(struct vagent_ops *va, int fd) +{ + int i; + + for (i = 0; i < va->num_socks; i++) + { + if (va->socks[i] == NULL) continue; + if (va->socks[i]->c == fd) + { + sock_redir_free(va, va->socks[i]); + va->socks[i] = NULL; + return True; + } + } + + return False; +} + +void start_agent(struct vagent_ops *va) +{ + int s, c; + + s = va->get_agent_sock(va->id); + + while (1) + { + int i; + fd_set fds; + int num; + struct sockaddr_un addr; + int in_addrlen = sizeof(addr); + int maxfd = s; + + FD_ZERO(&fds); + FD_SET(s, &fds); + + for (i = 0; i < va->num_socks; i++) + { + if (va->socks[i] != NULL) + { + int fd = va->socks[i]->c; + FD_SET(fd, &fds); + maxfd = MAX(maxfd, fd); + + if (va->socks[i]->n != NULL) + { + fd = va->socks[i]->s; + FD_SET(fd, &fds); + maxfd = MAX(fd, maxfd); + } + } + } + + dbgflush(); + num = sys_select(maxfd+1,&fds,NULL, NULL); + + if (num <= 0) + { + continue; + } + + if (FD_ISSET(s, &fds)) + { + FD_CLR(s, &fds); + c = accept(s, (struct sockaddr*)&addr, &in_addrlen); + if (c != -1) + { + sock_add(va, c); + } + } + + for (i = 0; i < va->num_socks; i++) + { + if (va->socks[i] == NULL) + { + continue; + } + if (FD_ISSET(va->socks[i]->c, &fds)) + { + FD_CLR(va->socks[i]->c, &fds); + if (!va->process_cli_sock(va->socks, + va->num_socks, + va->socks[i])) + { + sock_redir_free(va, va->socks[i]); + va->socks[i] = NULL; + } + } + if (va->socks[i] == NULL) + { + continue; + } + if (va->socks[i]->n == NULL) + { + continue; + } + if (FD_ISSET(va->socks[i]->s, &fds)) + { + FD_CLR(va->socks[i]->s, &fds); + if (!va->process_srv_sock(va->socks, + va->num_socks, + va->socks[i]->s)) + { + sock_redir_free(va, va->socks[i]); + va->socks[i] = NULL; + } + } + } + } +} + diff --git a/source3/utils/smb-agent.c b/source3/utils/smb-agent.c index 457631c307..5d1aa4db04 100644 --- a/source3/utils/smb-agent.c +++ b/source3/utils/smb-agent.c @@ -38,139 +38,19 @@ static char packet[BUFFER_SIZE]; extern int DEBUGLEVEL; -struct sock_redir -{ - int c; - int s; - int mid_offset; - struct cli_state *n; -}; - -static uint32 num_socks = 0; -static struct sock_redir **socks = NULL; static uint16 mid_offset = 0x0; /**************************************************************************** terminate sockent connection ****************************************************************************/ -static void sock_redir_free(struct sock_redir *sock) -{ - close(sock->c); - sock->c = -1; - if (sock->n != NULL) - { - sock->n->fd = sock->s; - cli_net_use_del(sock->n->desthost, &sock->n->usr, - False, NULL); - sock->n = NULL; - } - free(sock); -} - -/**************************************************************************** -free a sockent array -****************************************************************************/ -static void free_sock_array(uint32 num_entries, struct sock_redir **entries) +static void free_sock(void *sock) { - void(*fn)(void*) = (void(*)(void*))&sock_redir_free; - free_void_array(num_entries, (void**)entries, *fn); -} - -/**************************************************************************** -add a sockent state to the array -****************************************************************************/ -static struct sock_redir* add_sock_to_array(uint32 *len, - struct sock_redir ***array, - struct sock_redir *sock) -{ - int i; - for (i = 0; i < num_socks; i++) - { - if (socks[i] == NULL) - { - socks[i] = sock; - return sock; - } - } - - return (struct sock_redir*)add_item_to_array(len, - (void***)array, (void*)sock); - -} - -/**************************************************************************** -initiate sockent array -****************************************************************************/ -void init_sock_redir(void) -{ - socks = NULL; - num_socks = 0; -} - -/**************************************************************************** -terminate sockent array -****************************************************************************/ -void free_sock_redir(void) -{ - free_sock_array(num_socks, socks); - init_sock_redir(); -} - -/**************************************************************************** -create a new sockent state from user credentials -****************************************************************************/ -static struct sock_redir *sock_redir_get(int fd) -{ - struct sock_redir *sock = (struct sock_redir*)malloc(sizeof(*sock)); - - if (sock == NULL) - { - return NULL; - } - - ZERO_STRUCTP(sock); - - sock->c = fd; - sock->n = NULL; - sock->mid_offset = mid_offset; - - DEBUG(10,("sock_redir_get:\tfd:\t%d\tmidoff:\t%d\n", fd, mid_offset)); - - return sock; -} - -/**************************************************************************** -init sock state -****************************************************************************/ -static void sock_add(int fd) -{ - struct sock_redir *sock; - sock = sock_redir_get(fd); if (sock != NULL) { - add_sock_to_array(&num_socks, &socks, sock); - } -} - -/**************************************************************************** -delete a sockent state -****************************************************************************/ -static BOOL sock_del(int fd) -{ - int i; - - for (i = 0; i < num_socks; i++) - { - if (socks[i] == NULL) continue; - if (socks[i]->c == fd) - { - sock_redir_free(socks[i]); - socks[i] = NULL; - return True; - } + struct cli_state *n = (struct cli_state*)sock; + cli_net_use_del(n->desthost, &n->usr, + False, NULL); } - - return False; } static struct cli_state *init_client_connection(int c) @@ -325,9 +205,10 @@ static void filter_reply(char *buf, int moff) } -static BOOL process_cli_sock(struct sock_redir *sock) +static BOOL process_cli_sock(struct sock_redir **socks, uint32 num_socks, + struct sock_redir *sock) { - struct cli_state *n = sock->n; + struct cli_state *n = (struct cli_state*)sock->n; if (n == NULL) { n = init_client_connection(sock->c); @@ -335,7 +216,9 @@ static BOOL process_cli_sock(struct sock_redir *sock) { return False; } - sock->n = n; + sock->n = (void*)n; + sock->s_id = mid_offset; + sock->s = n->fd; } else { @@ -345,7 +228,7 @@ static BOOL process_cli_sock(struct sock_redir *sock) return False; } - filter_reply(packet, sock->mid_offset); + filter_reply(packet, sock->s_id); /* ignore keep-alives */ if (CVAL(packet, 0) != 0x85) { @@ -371,7 +254,8 @@ static int get_smbmid(char *buf) return SVAL(buf,smb_mid); } -static BOOL process_srv_sock(int fd) +static BOOL process_srv_sock(struct sock_redir **socks, uint32 num_socks, + int fd) { int smbmid; int i; @@ -393,16 +277,18 @@ static BOOL process_srv_sock(int fd) for (i = 0; i < num_socks; i++) { int moff; + struct cli_state *n; if (socks[i] == NULL || socks[i]->n == NULL) { continue; } - moff = socks[i]->mid_offset; + moff = socks[i]->s_id; + n = (struct cli_state*)socks[i]->n; DEBUG(10,("list:\tfd:\t%d\tmid:\t%d\tmoff:\t%d\n", socks[i]->s, - socks[i]->n->mid, + n->mid, moff)); - if (smbmid != socks[i]->n->mid + moff) + if (smbmid != n->mid + moff) { continue; } @@ -417,15 +303,13 @@ static BOOL process_srv_sock(int fd) return False; } -static void start_agent(void) +static int get_agent_sock(void *id) { - int s, c; + int s; struct sockaddr_un sa; fstring path; fstring dir; - CatchChild(); - slprintf(dir, sizeof(dir)-1, "/tmp/.smb.%d", getuid()); mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR); @@ -470,88 +354,25 @@ static void start_agent(void) DEBUG(0,("listen failed\n")); remove(path); } + return s; +} - while (1) +static void start_smb_agent(void) +{ + struct vagent_ops va = { - int i; - fd_set fds; - int num; - struct sockaddr_un addr; - int in_addrlen = sizeof(addr); - int maxfd = s; - - FD_ZERO(&fds); - FD_SET(s, &fds); - - for (i = 0; i < num_socks; i++) - { - if (socks[i] != NULL) - { - int fd = socks[i]->c; - FD_SET(fd, &fds); - maxfd = MAX(maxfd, fd); - - if (socks[i]->n != NULL) - { - fd = socks[i]->s; - FD_SET(fd, &fds); - maxfd = MAX(fd, maxfd); - } - } - } - - dbgflush(); - num = sys_select(maxfd+1,&fds,NULL, NULL); - - if (num <= 0) - { - continue; - } - - if (FD_ISSET(s, &fds)) - { - FD_CLR(s, &fds); - c = accept(s, (struct sockaddr*)&addr, &in_addrlen); - if (c != -1) - { - sock_add(c); - } - } + free_sock, + get_agent_sock, + process_cli_sock, + process_srv_sock, + NULL, + NULL, + 0 + }; + + CatchChild(); - for (i = 0; i < num_socks; i++) - { - if (socks[i] == NULL) - { - continue; - } - if (FD_ISSET(socks[i]->c, &fds)) - { - FD_CLR(socks[i]->c, &fds); - if (!process_cli_sock(socks[i])) - { - sock_redir_free(socks[i]); - socks[i] = NULL; - } - } - if (socks[i] == NULL) - { - continue; - } - if (socks[i]->n == NULL) - { - continue; - } - if (FD_ISSET(socks[i]->s, &fds)) - { - FD_CLR(socks[i]->s, &fds); - if (!process_srv_sock(socks[i]->s)) - { - sock_redir_free(socks[i]); - socks[i] = NULL; - } - } - } - } + start_agent(&va); } /**************************************************************************** @@ -612,7 +433,7 @@ int main(int argc, char *argv[]) become_daemon(); } - start_agent(); + start_smb_agent(); return 0; } |