diff options
author | cvs2svn Import User <samba-bugs@samba.org> | 2002-07-14 22:15:21 +0000 |
---|---|---|
committer | cvs2svn Import User <samba-bugs@samba.org> | 2002-07-14 22:15:21 +0000 |
commit | ec167dc9cc0ec2ee461837c25a371d2981744208 (patch) | |
tree | 2703197421fecfa142935091760c2d4a60f10552 /source3 | |
parent | a2c8ca186f7261fdab49ed40949320a45868d2b5 (diff) | |
parent | 13157d1494b99bf85632120c27286ba4d877a68f (diff) | |
download | samba-ec167dc9cc0ec2ee461837c25a371d2981744208.tar.gz samba-ec167dc9cc0ec2ee461837c25a371d2981744208.tar.bz2 samba-ec167dc9cc0ec2ee461837c25a371d2981744208.zip |
This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to be commit b8d39651fb90ef170055735412417239a63afc5d)
Diffstat (limited to 'source3')
30 files changed, 4000 insertions, 0 deletions
diff --git a/source3/lib/data_blob.c b/source3/lib/data_blob.c new file mode 100644 index 0000000000..d690cd05a0 --- /dev/null +++ b/source3/lib/data_blob.c @@ -0,0 +1,109 @@ +/* + Unix SMB/CIFS implementation. + Easy management of byte-length data + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2001 + + 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" + +/******************************************************************* + free() a data blob +*******************************************************************/ +static void free_data_blob(DATA_BLOB *d) +{ + if ((d) && (d->free)) { + SAFE_FREE(d->data); + } +} + +/******************************************************************* + construct a data blob, must be freed with data_blob_free() + you can pass NULL for p and get a blank data blob +*******************************************************************/ +DATA_BLOB data_blob(const void *p, size_t length) +{ + DATA_BLOB ret; + + if (!length) { + ZERO_STRUCT(ret); + return ret; + } + + if (p) { + ret.data = smb_xmemdup(p, length); + } else { + ret.data = smb_xmalloc(length); + } + ret.length = length; + ret.free = free_data_blob; + return ret; +} + +/******************************************************************* + construct a data blob, using supplied TALLOC_CTX +*******************************************************************/ +DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) +{ + DATA_BLOB ret; + + if (!p || !length) { + ZERO_STRUCT(ret); + return ret; + } + + ret.data = talloc_memdup(mem_ctx, p, length); + if (ret.data == NULL) + smb_panic("data_blob_talloc: talloc_memdup failed.\n"); + + ret.length = length; + ret.free = NULL; + return ret; +} + +/******************************************************************* +free a data blob +*******************************************************************/ +void data_blob_free(DATA_BLOB *d) +{ + if (d) { + if (d->free) { + (d->free)(d); + } + ZERO_STRUCTP(d); + } +} + +/******************************************************************* +clear a DATA_BLOB's contents +*******************************************************************/ +static void data_blob_clear(DATA_BLOB *d) +{ + if (d->data) { + memset(d->data, 0, d->length); + } +} + +/******************************************************************* +free a data blob and clear its contents +*******************************************************************/ +void data_blob_clear_free(DATA_BLOB *d) +{ + data_blob_clear(d); + data_blob_free(d); +} + diff --git a/source3/lib/server_mutex.c b/source3/lib/server_mutex.c new file mode 100644 index 0000000000..416d77564d --- /dev/null +++ b/source3/lib/server_mutex.c @@ -0,0 +1,57 @@ +/* + Unix SMB/CIFS implementation. + Authenticate against a remote domain + Copyright (C) Andrew Tridgell 1992-2002 + Copyright (C) Andrew Bartlett 2002 + + 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" + +/* For reasons known only to MS, many of their NT/Win2k versions + need serialised access only. Two connections at the same time + may (in certain situations) cause connections to be reset, + or access to be denied. + + This locking allows smbd's mutlithread architecture to look + like the single-connection that NT makes. */ + +static char *mutex_server_name; + +BOOL grab_server_mutex(const char *name) +{ + mutex_server_name = strdup(name); + if (!mutex_server_name) { + DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name)); + return False; + } + if (!message_named_mutex(mutex_server_name, 20)) { + DEBUG(10,("grab_server_mutex: failed for %s\n", name)); + SAFE_FREE(mutex_server_name); + return False; + } + + return True; +} + +void release_server_mutex(void) +{ + if (mutex_server_name) { + message_named_mutex_release(mutex_server_name); + SAFE_FREE(mutex_server_name); + } +} + diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c new file mode 100644 index 0000000000..dac90908c4 --- /dev/null +++ b/source3/libads/kerberos_verify.c @@ -0,0 +1,151 @@ +/* + Unix SMB/CIFS implementation. + kerberos utility library + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Remus Koos 2001 + + + 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" + +#ifdef HAVE_KRB5 + +/* + verify an incoming ticket and parse out the principal name and + authorization_data if available +*/ +NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, + char **principal, DATA_BLOB *auth_data) +{ + krb5_context context; + krb5_auth_context auth_context = NULL; + krb5_keytab keytab = NULL; + krb5_data packet; + krb5_ticket *tkt = NULL; + krb5_data salt; + krb5_encrypt_block eblock; + int ret; + krb5_keyblock * key; + krb5_principal host_princ; + char *host_princ_s; + extern pstring global_myname; + fstring myname; + char *password_s; + krb5_data password; + + if (!secrets_init()) { + DEBUG(1,("secrets_init failed\n")); + return NT_STATUS_LOGON_FAILURE; + } + + password_s = secrets_fetch_machine_password(); + if (!password_s) { + DEBUG(1,("failed to fetch machine password\n")); + return NT_STATUS_LOGON_FAILURE; + } + + password.data = password_s; + password.length = strlen(password_s); + + ret = krb5_init_context(&context); + if (ret) { + DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + ret = krb5_set_default_realm(context, ads->realm); + if (ret) { + DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret))); + ads_destroy(&ads); + return NT_STATUS_LOGON_FAILURE; + } + + /* this whole process is far more complex than I would + like. We have to go through all this to allow us to store + the secret internally, instead of using /etc/krb5.keytab */ + ret = krb5_auth_con_init(context, &auth_context); + if (ret) { + DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + fstrcpy(myname, global_myname); + strlower(myname); + asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm()); + ret = krb5_parse_name(context, host_princ_s, &host_princ); + if (ret) { + DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + ret = krb5_principal2salt(context, host_princ, &salt); + if (ret) { + DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { + return NT_STATUS_NO_MEMORY; + } + + krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_MD5); + + ret = krb5_string_to_key(context, &eblock, key, &password, &salt); + if (ret) { + DEBUG(1,("krb5_string_to_key failed (%s)\n", error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + krb5_auth_con_setuseruserkey(context, auth_context, key); + + packet.length = ticket->length; + packet.data = (krb5_pointer)ticket->data; + +#if 0 + file_save("/tmp/ticket.dat", ticket->data, ticket->length); +#endif + + if ((ret = krb5_rd_req(context, &auth_context, &packet, + NULL, keytab, NULL, &tkt))) { + DEBUG(3,("krb5_rd_req with auth failed (%s)\n", + error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + if (tkt->enc_part2) { + *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents, + tkt->enc_part2->authorization_data[0]->length); + } + +#if 0 + if (tkt->enc_part2) { + file_save("/tmp/authdata.dat", + tkt->enc_part2->authorization_data[0]->contents, + tkt->enc_part2->authorization_data[0]->length); + } +#endif + + if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, principal))) { + DEBUG(3,("krb5_unparse_name failed (%s)\n", + error_message(ret))); + return NT_STATUS_LOGON_FAILURE; + } + + return NT_STATUS_OK; +} + +#endif diff --git a/source3/libsmb/cli_spoolss_notify.c b/source3/libsmb/cli_spoolss_notify.c new file mode 100644 index 0000000000..922b0fbb1d --- /dev/null +++ b/source3/libsmb/cli_spoolss_notify.c @@ -0,0 +1,223 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Gerald Carter 2001-2002, + Copyright (C) Tim Potter 2000-2002, + Copyright (C) Andrew Tridgell 1994-2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + Copyright (C) Jean-Francois Micouleau 1999-2000. + + 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" + +/* + * SPOOLSS Client RPC's used by servers as the notification + * back channel. + */ + +/* Send a ReplyOpenPrinter request. This rpc is made by the printer + server to the printer client in response to a rffpcnex request. + The rrfpcnex request names a printer and a handle (the printerlocal + value) and this rpc establishes a back-channel over which printer + notifications are performed. */ + +WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char *printer, uint32 printerlocal, uint32 type, + POLICY_HND *handle) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_REPLYOPENPRINTER q; + SPOOL_R_REPLYOPENPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + /* Initialise input parameters */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type); + + /* Marshall data and send request */ + + if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0)) + goto done; + + /* Return result */ + + memcpy(handle, &r.handle, sizeof(r.handle)); + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Close a back-channel notification connection */ + +WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *handle) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_REPLYCLOSEPRINTER q; + SPOOL_R_REPLYCLOSEPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + /* Initialise input parameters */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_reply_closeprinter(&q, handle); + + /* Marshall data and send request */ + + if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0)) + goto done; + + /* Return result */ + + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/********************************************************************* + This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change + notification event when the registration **did not** use + SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor. + Also see cli_spolss_reply_rrpcn() + *********************************************************************/ + +WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 condition, uint32 change_id) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ROUTERREPLYPRINTER q; + SPOOL_R_ROUTERREPLYPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + /* Initialise input parameters */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id); + + /* Marshall data and send request */ + + if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/********************************************************************* + This SPOOLSS_REPLY_RRPCN function is used to send a change + notification event when the registration **did** use + SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor + Also see cli_spoolss_routereplyprinter() + *********************************************************************/ + +WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 notify_data_len, + SPOOL_NOTIFY_INFO_DATA *notify_data, + uint32 change_low, uint32 change_high) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_REPLY_RRPCN q; + SPOOL_R_REPLY_RRPCN r; + WERROR result = W_ERROR(ERRgeneral); + SPOOL_NOTIFY_INFO notify_info; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + ZERO_STRUCT(notify_info); + + /* Initialise input parameters */ + + notify_info.version = 0x2; + notify_info.flags = 0x00020000; /* ?? */ + notify_info.count = notify_data_len; + notify_info.data = notify_data; + + /* create and send a MSRPC command with api */ + /* store the parameters */ + + make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high, + ¬ify_info); + + /* Marshall data and send request */ + + if(!spoolss_io_q_reply_rrpcn("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0)) + goto done; + + if (r.unknown0 == 0x00080000) + DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n")); + + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c new file mode 100644 index 0000000000..34b818ee74 --- /dev/null +++ b/source3/libsmb/libsmb_cache.c @@ -0,0 +1,191 @@ +/* + Unix SMB/CIFS implementation. + SMB client library implementation (server cache) + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + + 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" + +/* + * Define this to get the real SMBCFILE and SMBCSRV structures + */ +#define _SMBC_INTERNAL +#include "libsmbclient.h" + +/* + * Structure we use if internal caching mechanism is used + * nothing fancy here. + */ +struct smbc_server_cache { + char *server_name; + char *share_name; + char *workgroup; + char *username; + SMBCSRV *server; + + struct smbc_server_cache *next, *prev; +}; + + + +/* + * Add a new connection to the server cache. + * This function is only used if the external cache is not enabled + */ +static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * new, + char * server, char * share, + char * workgroup, char * username) +{ + struct smbc_server_cache * srvcache = NULL; + + if (!(srvcache = malloc(sizeof(*srvcache)))) { + errno = ENOMEM; + DEBUG(3, ("Not enough space for server cache allocation\n")); + return 1; + } + + ZERO_STRUCTP(srvcache); + + srvcache->server = new; + + srvcache->server_name = strdup(server); + if (!srvcache->server_name) { + errno = ENOMEM; + goto failed; + } + + srvcache->share_name = strdup(share); + if (!srvcache->share_name) { + errno = ENOMEM; + goto failed; + } + + srvcache->workgroup = strdup(workgroup); + if (!srvcache->workgroup) { + errno = ENOMEM; + goto failed; + } + + srvcache->username = strdup(username); + if (!srvcache->username) { + errno = ENOMEM; + goto failed; + } + + DLIST_ADD(((struct smbc_server_cache *)context->server_cache), srvcache); + return 0; + + failed: + SAFE_FREE(srvcache->server_name); + SAFE_FREE(srvcache->share_name); + SAFE_FREE(srvcache->workgroup); + SAFE_FREE(srvcache->username); + + return 1; +} + + + +/* + * Search the server cache for a server + * returns server_fd on success, -1 on error (not found) + * This function is only used if the external cache is not enabled + */ +static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, char * server, + char * share, char * workgroup, char * user) +{ + struct smbc_server_cache * srv = NULL; + + /* Search the cache lines */ + for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) { + if (strcmp(server,srv->server_name) == 0 && + strcmp(share,srv->share_name) == 0 && + strcmp(workgroup,srv->workgroup) == 0 && + strcmp(user, srv->username) == 0) + return srv->server; + } + + return NULL; +} + + +/* + * Search the server cache for a server and remove it + * returns 0 on success + * This function is only used if the external cache is not enabled + */ +static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server) +{ + struct smbc_server_cache * srv = NULL; + + for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) { + if (server == srv->server) { + + /* remove this sucker */ + DLIST_REMOVE(((struct smbc_server_cache *)context->server_cache), srv); + SAFE_FREE(srv->server_name); + SAFE_FREE(srv->share_name); + SAFE_FREE(srv->workgroup); + SAFE_FREE(srv->username); + SAFE_FREE(srv); + return 0; + } + } + /* server not found */ + return 1; +} + + +/* + * Try to remove all the servers in cache + * returns 1 on failure and 0 if all servers could be removed. + */ +static int smbc_purge_cached(SMBCCTX * context) +{ + struct smbc_server_cache * srv = NULL; + int could_not_purge_all = 0; + + for (srv=((struct smbc_server_cache *) context->server_cache);srv;srv=srv->next) { + if (smbc_remove_unused_server(context, srv->server)) { + /* could not be removed */ + could_not_purge_all = 1; + } + } + return could_not_purge_all; +} + + + +/* + * This functions initializes all server-cache related functions + * to the default (internal) system. + * + * We use this to make the rest of the cache system static. + */ + +int smbc_default_cache_functions(SMBCCTX * context) +{ + context->callbacks.add_cached_srv_fn = smbc_add_cached_server; + context->callbacks.get_cached_srv_fn = smbc_get_cached_server; + context->callbacks.remove_cached_srv_fn = smbc_remove_cached_server; + context->callbacks.purge_cached_fn = smbc_purge_cached; + + return 0; +} diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c new file mode 100644 index 0000000000..dbfd860358 --- /dev/null +++ b/source3/libsmb/libsmb_compat.c @@ -0,0 +1,285 @@ +/* + Unix SMB/CIFS implementation. + SMB client library implementation (Old interface compatibility) + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000 + Copyright (C) John Terpstra 2000 + Copyright (C) Tom Jansen (Ninja ISD) 2002 + + 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" + +/* + * Define this to get the real SMBCFILE and SMBCSRV structures + */ +#define _SMBC_INTERNAL +#include "libsmbclient.h" + +struct smbc_compat_fdlist { + SMBCFILE * file; + int fd; + struct smbc_compat_fdlist *next, *prev; +}; + +static SMBCCTX * statcont = NULL; +static int smbc_compat_initialized = 0; +static int smbc_currentfd = 10000; +static struct smbc_compat_fdlist * smbc_compat_fdlist = NULL; + + +/* Find an fd and return the SMBCFILE * or NULL on failure */ +static SMBCFILE * find_fd(int fd) +{ + struct smbc_compat_fdlist * f = smbc_compat_fdlist; + while (f) { + if (f->fd == fd) + return f->file; + f = f->next; + } + return NULL; +} + +/* Add an fd, returns 0 on success, -1 on error with errno set */ +static int add_fd(SMBCFILE * file) +{ + struct smbc_compat_fdlist * f = malloc(sizeof(struct smbc_compat_fdlist)); + if (!f) { + errno = ENOMEM; + return -1; + } + + f->fd = smbc_currentfd++; + f->file = file; + + DLIST_ADD(smbc_compat_fdlist, f); + + return f->fd; +} + + + +/* Delete an fd, returns 0 on success */ +static int del_fd(int fd) +{ + struct smbc_compat_fdlist * f = smbc_compat_fdlist; + while (f) { + if (f->fd == fd) + break; + f = f->next; + } + if (f) { + /* found */ + DLIST_REMOVE(smbc_compat_fdlist, f); + SAFE_FREE(f); + return 0; + } + return 1; +} + + + +int smbc_init(smbc_get_auth_data_fn fn, int debug) +{ + if (!smbc_compat_initialized) { + statcont = smbc_new_context(); + if (!statcont) + return -1; + + statcont->debug = debug; + statcont->callbacks.auth_fn = fn; + + if (!smbc_init_context(statcont)) { + smbc_free_context(statcont, False); + return -1; + } + + smbc_compat_initialized = 1; + + return 0; + } + return 0; +} + + +int smbc_open(const char *furl, int flags, mode_t mode) +{ + SMBCFILE * file; + int fd; + + file = statcont->open(statcont, furl, flags, mode); + if (!file) + return -1; + + fd = add_fd(file); + if (fd == -1) + statcont->close(statcont, file); + return fd; +} + + +int smbc_creat(const char *furl, mode_t mode) +{ + SMBCFILE * file; + int fd; + + file = statcont->creat(statcont, furl, mode); + if (!file) + return -1; + + fd = add_fd(file); + if (fd == -1) { + /* Hmm... should we delete the file too ? I guess we could try */ + statcont->close(statcont, file); + statcont->unlink(statcont, furl); + } + return fd; +} + + +ssize_t smbc_read(int fd, void *buf, size_t bufsize) +{ + SMBCFILE * file = find_fd(fd); + return statcont->read(statcont, file, buf, bufsize); +} + +ssize_t smbc_write(int fd, void *buf, size_t bufsize) +{ + SMBCFILE * file = find_fd(fd); + return statcont->write(statcont, file, buf, bufsize); +} + +off_t smbc_lseek(int fd, off_t offset, int whence) +{ + SMBCFILE * file = find_fd(fd); + return statcont->lseek(statcont, file, offset, whence); +} + +int smbc_close(int fd) +{ + SMBCFILE * file = find_fd(fd); + del_fd(fd); + return statcont->close(statcont, file); +} + +int smbc_unlink(const char *fname) +{ + return statcont->unlink(statcont, fname); +} + +int smbc_rename(const char *ourl, const char *nurl) +{ + return statcont->rename(statcont, ourl, statcont, nurl); +} + +int smbc_opendir(const char *durl) +{ + SMBCFILE * file; + int fd; + + file = statcont->opendir(statcont, durl); + if (!file) + return -1; + + fd = add_fd(file); + if (fd == -1) + statcont->closedir(statcont, file); + + return fd; +} + +int smbc_closedir(int dh) +{ + SMBCFILE * file = find_fd(dh); + del_fd(dh); + return statcont->closedir(statcont, file); +} + +int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count) +{ + SMBCFILE * file = find_fd(dh); + return statcont->getdents(statcont, file,dirp, count); +} + +struct smbc_dirent* smbc_readdir(unsigned int dh) +{ + SMBCFILE * file = find_fd(dh); + return statcont->readdir(statcont, file); +} + +off_t smbc_telldir(int dh) +{ + SMBCFILE * file = find_fd(dh); + return statcont->telldir(statcont, file); +} + +int smbc_lseekdir(int fd, off_t offset) +{ + SMBCFILE * file = find_fd(fd); + return statcont->lseekdir(statcont, file, offset); +} + +int smbc_mkdir(const char *durl, mode_t mode) +{ + return statcont->mkdir(statcont, durl, mode); +} + +int smbc_rmdir(const char *durl) +{ + return statcont->rmdir(statcont, durl); +} + +int smbc_stat(const char *url, struct stat *st) +{ + return statcont->stat(statcont, url, st); +} + +int smbc_fstat(int fd, struct stat *st) +{ + SMBCFILE * file = find_fd(fd); + return statcont->fstat(statcont, file, st); +} + +int smbc_chmod(const char *url, mode_t mode) +{ + /* NOT IMPLEMENTED IN LIBSMBCLIENT YET */ + return -1; +} + +int smbc_print_file(const char *fname, const char *printq) +{ + return statcont->print_file(statcont, fname, statcont, printq); +} + +int smbc_open_print_job(const char *fname) +{ + SMBCFILE * file = statcont->open_print_job(statcont, fname); + if (!file) return -1; + return (int) file; +} + +int smbc_list_print_jobs(const char *purl, smbc_get_print_job_info fn) +{ + return statcont->list_print_jobs(statcont, purl, fn); +} + +int smbc_unlink_print_job(const char *purl, int id) +{ + return statcont->unlink_print_job(statcont, purl, id); +} + + diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c new file mode 100644 index 0000000000..d32d62edaa --- /dev/null +++ b/source3/nsswitch/winbindd_dual.c @@ -0,0 +1,209 @@ +/* + Unix SMB/CIFS implementation. + + Winbind background daemon + + Copyright (C) Andrew Tridgell 2002 + + 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. +*/ + +/* + the idea of the optional dual daemon mode is ot prevent slow domain + responses from clagging up the rest of the system. When in dual + daemon mode winbindd always responds to requests from cache if the + request is in cache, and if the cached answer is stale then it asks + the "dual daemon" to update the cache for that request + + */ + +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +extern BOOL opt_dual_daemon; +BOOL backgroud_process = False; +int dual_daemon_pipe = -1; + + +/* a list of requests ready to be sent to the dual daemon */ +struct dual_list { + struct dual_list *next; + char *data; + int length; + int offset; +}; + +static struct dual_list *dual_list; +static struct dual_list *dual_list_end; + +/* + setup a select() including the dual daemon pipe + */ +int dual_select_setup(fd_set *fds, int maxfd) +{ + if (dual_daemon_pipe == -1 || + !dual_list) { + return maxfd; + } + + FD_SET(dual_daemon_pipe, fds); + if (dual_daemon_pipe > maxfd) { + maxfd = dual_daemon_pipe; + } + return maxfd; +} + + +/* + a hook called from the main winbindd select() loop to handle writes + to the dual daemon pipe +*/ +void dual_select(fd_set *fds) +{ + int n; + + if (dual_daemon_pipe == -1 || + !dual_list || + !FD_ISSET(dual_daemon_pipe, fds)) { + return; + } + + n = write(dual_daemon_pipe, + &dual_list->data[dual_list->offset], + dual_list->length - dual_list->offset); + + if (n <= 0) { + /* the pipe is dead! fall back to normal operation */ + dual_daemon_pipe = -1; + return; + } + + dual_list->offset += n; + + if (dual_list->offset == dual_list->length) { + struct dual_list *next; + next = dual_list->next; + free(dual_list->data); + free(dual_list); + dual_list = next; + if (!dual_list) { + dual_list_end = NULL; + } + } +} + +/* + send a request to the background daemon + this is called for stale cached entries +*/ +void dual_send_request(struct winbindd_cli_state *state) +{ + struct dual_list *list; + + if (!backgroud_process) return; + + list = malloc(sizeof(*list)); + if (!list) return; + + list->next = NULL; + list->data = memdup(&state->request, sizeof(state->request)); + list->length = sizeof(state->request); + list->offset = 0; + + if (!dual_list_end) { + dual_list = list; + dual_list_end = list; + } else { + dual_list_end->next = list; + dual_list_end = list; + } + + backgroud_process = False; +} + + +/* +the main dual daemon +*/ +void do_dual_daemon(void) +{ + int fdpair[2]; + struct winbindd_cli_state state; + + if (pipe(fdpair) != 0) { + return; + } + + ZERO_STRUCT(state); + state.pid = getpid(); + + dual_daemon_pipe = fdpair[1]; + state.sock = fdpair[0]; + + if (fork() != 0) { + close(fdpair[0]); + return; + } + close(fdpair[1]); + + if (winbind_setup_common() != 0) _exit(0); + + dual_daemon_pipe = -1; + opt_dual_daemon = False; + + while (1) { + /* free up any talloc memory */ + lp_talloc_free(); + main_loop_talloc_free(); + + /* fetch a request from the main daemon */ + winbind_client_read(&state); + + if (state.finished) { + /* we lost contact with our parent */ + exit(0); + } + + /* process full rquests */ + if (state.read_buf_len == sizeof(state.request)) { + DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd)); + + /* special handling for the stateful requests */ + switch (state.request.cmd) { + case WINBINDD_GETPWENT: + winbindd_setpwent(&state); + break; + + case WINBINDD_GETGRENT: + case WINBINDD_GETGRLST: + winbindd_setgrent(&state); + break; + default: + break; + } + + winbind_process_packet(&state); + SAFE_FREE(state.response.extra_data); + + free_getent_state(state.getpwent_state); + free_getent_state(state.getgrent_state); + state.getpwent_state = NULL; + state.getgrent_state = NULL; + } + } +} + diff --git a/source3/pam_smbpass/INSTALL b/source3/pam_smbpass/INSTALL new file mode 100644 index 0000000000..ae2ba02bbb --- /dev/null +++ b/source3/pam_smbpass/INSTALL @@ -0,0 +1,64 @@ + +Because pam_smbpass is derived from the Samba smbpasswd utility, recent +versions of pam_smbpass require a copy of the Samba source code to be +available on the build system. Version 0.7.5 has been tested against +Samba 2.2.0-alpha3, and this is the recommended version of Samba to use +for building pam_smbpass. This only affects /building/ pam_smbpass; you +can still run any version of the Samba server that you want, although +clearly it saves some disk space to have only one copy of the source +code on your system (Samba 2.2.0-alpha3 takes roughly 32MB of disk space +to build pam_smbpass). + +Version 0.7.5 features a new build system to make it easier to build +pam_smbpass. + + +Using the new build system +========================== + +If you don't have a copy of the Samba source code on your machine, and you +don't have a preferred Samba version (or mirror site), you can build +pam_smbpass by just typing 'make'. + +If you want to use a version other than 2.2.0-alpha3, or you want to +download the source code from a faster Samba mirror (see +<http://us1.samba.org/samba/> for a list of mirror sites), please download +the source code and unpack it before running make. The build scripts will +attempt to autodetect your Samba source directory, and if it can't be +found automatically, you will be given the opportunity to specify an +alternate directory for the Samba sources. + +Feedback is welcome if you try (or succeed!) to build pam_smbpass with +other versions of Samba. + + +Options to 'make' +================= + +By default, pam_smbpass will configure the Samba build tree with the +options + + --with-fhs --with-privatedir=/etc --with-configdir=/etc + +This will configure pam_smbpass to look for the smbpasswd file as +/etc/smbpasswd (or /etc/smbpasswd.tdb), and the smb.conf file as +/etc/smb.conf. You can override these options by setting CONFIGOPTS when +calling make. E.g., if you have your smb.conf file in /usr/etc and your +smbpasswd file in /usr/etc/private, you might run + + make CONFIGOPTS="--with-privatedir=/usr/etc/private --with-configdir=/usr/etc" + +For a complete list of available configuration options, see +'./samba/configure --help' + + +Installing the module +===================== + +If all goes well in the build process, the file pam_smbpass.so will be +created in the current directory. Simply install the module into your +system's PAM module directory: + + install -m 755 -s bin/pam_smbpass.so /lib/security + +and you're all set. diff --git a/source3/passdb/pdb_compat.c b/source3/passdb/pdb_compat.c new file mode 100644 index 0000000000..713c92e3ac --- /dev/null +++ b/source3/passdb/pdb_compat.c @@ -0,0 +1,104 @@ +/* + Unix SMB/CIFS implementation. + SAM_ACCOUNT access routines + Copyright (C) Jeremy Allison 1996-2001 + Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + Copyright (C) Gerald (Jerry) Carter 2000-2001 + Copyright (C) Andrew Bartlett 2001-2002 + Copyright (C) Stefan (metze) Metzmacher 2002 + + 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + +uint32 pdb_get_user_rid (const SAM_ACCOUNT *sampass) +{ + uint32 u_rid; + + if (sampass) + if (sid_peek_check_rid(get_global_sam_sid(), pdb_get_user_sid(sampass),&u_rid)) + return u_rid; + + return (0); +} + +uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass) +{ + uint32 g_rid; + + if (sampass) + if (sid_peek_check_rid(get_global_sam_sid(), pdb_get_group_sid(sampass),&g_rid)) + return g_rid; + return (0); +} + +BOOL pdb_set_user_sid_from_rid (SAM_ACCOUNT *sampass, uint32 rid) +{ + DOM_SID u_sid; + const DOM_SID *global_sam_sid; + + if (!sampass) + return False; + + if (!(global_sam_sid = get_global_sam_sid())) { + DEBUG(1, ("pdb_set_user_sid_from_rid: Could not read global sam sid!\n")); + return False; + } + + sid_copy(&u_sid, global_sam_sid); + + if (!sid_append_rid(&u_sid, rid)) + return False; + + if (!pdb_set_user_sid(sampass, &u_sid)) + return False; + + DEBUG(10, ("pdb_set_user_sid_from_rid:\n\tsetting user sid %s from rid %d\n", + sid_string_static(&u_sid),rid)); + + return True; +} + +BOOL pdb_set_group_sid_from_rid (SAM_ACCOUNT *sampass, uint32 grid) +{ + DOM_SID g_sid; + const DOM_SID *global_sam_sid; + + if (!sampass) + return False; + + if (!(global_sam_sid = get_global_sam_sid())) { + DEBUG(1, ("pdb_set_user_sid_from_rid: Could not read global sam sid!\n")); + return False; + } + + sid_copy(&g_sid, global_sam_sid); + + if (!sid_append_rid(&g_sid, grid)) + return False; + + if (!pdb_set_group_sid(sampass, &g_sid)) + return False; + + DEBUG(10, ("pdb_set_group_sid_from_rid:\n\tsetting group sid %s from rid %d\n", + sid_string_static(&g_sid), grid)); + + return True; +} + diff --git a/source3/passdb/pdb_unix.c b/source3/passdb/pdb_unix.c new file mode 100644 index 0000000000..b4092b88f8 --- /dev/null +++ b/source3/passdb/pdb_unix.c @@ -0,0 +1,127 @@ +/* + * Unix password backend for samba + * Copyright (C) Jelmer Vernooij 2002 + * + * 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" + +/****************************************************************** + Lookup a name in the SAM database + ******************************************************************/ + +static BOOL unixsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname) +{ + struct passwd *pass; + if (!methods) { + DEBUG(0,("invalid methods\n")); + return False; + } + if (!sname) { + DEBUG(0,("invalid name specified")); + return False; + } + pass = Get_Pwnam(sname); + + return NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass)); +} + + +/*************************************************************************** + Search by rid + **************************************************************************/ + +static BOOL unixsam_getsampwrid (struct pdb_methods *methods, + SAM_ACCOUNT *user, uint32 rid) +{ + struct passwd *pass; + BOOL ret = False; + if (!methods) { + DEBUG(0,("invalid methods\n")); + return False; + } + + if (pdb_rid_is_user(rid)) { + pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid)); + + if (pass) { + ret = NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass)); + passwd_free(&pass); + } + } + return ret; +} + +static BOOL unixsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid) +{ + uint32 rid; + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) + return False; + return unixsam_getsampwrid(my_methods, user, rid); +} + +/*************************************************************************** + Adds an existing SAM_ACCOUNT + ****************************************************************************/ + +static BOOL unixsam_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd) +{ + DEBUG(0,("pdb_unix should not be listed as the first passdb backend! You can't add users to it.\n")); + return False; +} + +/*************************************************************************** + Updates a SAM_ACCOUNT + + This isn't a particulary practical option for pdb_unix. We certainly don't + want to twidde the filesystem, so what should we do? + + Current plan is to transparently add the account. It should appear + as if the pdb_unix version was modified, but its actually stored somehwere. + ****************************************************************************/ + +static BOOL unixsam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd) +{ + return methods->parent->pdb_add_sam_account(methods->parent, newpwd); +} + +NTSTATUS pdb_init_unixsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + + if (!pdb_context) { + DEBUG(0, ("invalid pdb_context specified\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + return nt_status; + } + + (*pdb_method)->name = "unixsam"; + + (*pdb_method)->setsampwent = NULL; + (*pdb_method)->endsampwent = NULL; + (*pdb_method)->getsampwent = NULL; + (*pdb_method)->getsampwnam = unixsam_getsampwnam; + (*pdb_method)->getsampwsid = unixsam_getsampwsid; + (*pdb_method)->add_sam_account = unixsam_add_sam_account; + (*pdb_method)->update_sam_account = unixsam_update_sam_account; + (*pdb_method)->delete_sam_account = NULL; + + /* There's not very much to initialise here */ + return NT_STATUS_OK; +} diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c new file mode 100644 index 0000000000..2c574f4a61 --- /dev/null +++ b/source3/passdb/util_sam_sid.c @@ -0,0 +1,275 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Luke Kenneth Caseson Leighton 1998-1999 + Copyright (C) Jeremy Allison 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" + +extern pstring global_myname; +extern fstring global_myworkgroup; + +#define MAX_SID_NAMES 7 + +typedef struct _known_sid_users { + uint32 rid; + enum SID_NAME_USE sid_name_use; + char *known_user_name; +} known_sid_users; + +static struct sid_name_map_info +{ + DOM_SID *sid; + char *name; + known_sid_users *known_users; +} sid_name_map[MAX_SID_NAMES]; + +extern DOM_SID global_sid_Builtin; /* Local well-known domain */ +extern DOM_SID global_sid_World_Domain; /* Everyone domain */ +extern DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner domain */ +extern DOM_SID global_sid_NT_Authority; /* NT Authority */ + + +static BOOL sid_name_map_initialized = False; +/* static known_sid_users no_users[] = {{0, 0, NULL}}; */ + +static known_sid_users everyone_users[] = { + { 0, SID_NAME_WKN_GRP, "Everyone" }, + {0, (enum SID_NAME_USE)0, NULL}}; + +static known_sid_users creator_owner_users[] = { + { 0, SID_NAME_ALIAS, "Creator Owner" }, + {0, (enum SID_NAME_USE)0, NULL}}; + +static known_sid_users nt_authority_users[] = { + { 1, SID_NAME_ALIAS, "Dialup" }, + { 2, SID_NAME_ALIAS, "Network"}, + { 3, SID_NAME_ALIAS, "Batch"}, + { 4, SID_NAME_ALIAS, "Interactive"}, + { 6, SID_NAME_ALIAS, "Service"}, + { 7, SID_NAME_ALIAS, "AnonymousLogon"}, + { 8, SID_NAME_ALIAS, "Proxy"}, + { 9, SID_NAME_ALIAS, "ServerLogon"}, + { 11, SID_NAME_ALIAS, "Authenticated Users"}, + { 18, SID_NAME_ALIAS, "SYSTEM"}, + { 0, (enum SID_NAME_USE)0, NULL}}; + +static known_sid_users builtin_groups[] = { + { BUILTIN_ALIAS_RID_ADMINS, SID_NAME_ALIAS, "Administrators" }, + { BUILTIN_ALIAS_RID_USERS, SID_NAME_ALIAS, "Users" }, + { BUILTIN_ALIAS_RID_GUESTS, SID_NAME_ALIAS, "Guests" }, + { BUILTIN_ALIAS_RID_ACCOUNT_OPS, SID_NAME_ALIAS, "Account Operators" }, + { BUILTIN_ALIAS_RID_SYSTEM_OPS, SID_NAME_ALIAS, "Server Operators" }, + { BUILTIN_ALIAS_RID_PRINT_OPS, SID_NAME_ALIAS, "Print Operators" }, + { BUILTIN_ALIAS_RID_BACKUP_OPS, SID_NAME_ALIAS, "Backup Operators" }, + { 0, (enum SID_NAME_USE)0, NULL}}; + + + +/************************************************************************** + quick init function + *************************************************************************/ +static void init_sid_name_map (void) +{ + int i = 0; + + if (sid_name_map_initialized) return; + + generate_wellknown_sids(); + + if ((lp_security() == SEC_USER) && lp_domain_logons()) { + sid_name_map[i].sid = get_global_sam_sid(); + sid_name_map[i].name = global_myworkgroup; + sid_name_map[i].known_users = NULL; + i++; + sid_name_map[i].sid = get_global_sam_sid(); + sid_name_map[i].name = global_myname; + sid_name_map[i].known_users = NULL; + i++; + } + else { + sid_name_map[i].sid = get_global_sam_sid(); + sid_name_map[i].name = global_myname; + sid_name_map[i].known_users = NULL; + i++; + } + + sid_name_map[i].sid = &global_sid_Builtin; + sid_name_map[i].name = "BUILTIN"; + sid_name_map[i].known_users = &builtin_groups[0]; + i++; + + sid_name_map[i].sid = &global_sid_World_Domain; + sid_name_map[i].name = ""; + sid_name_map[i].known_users = &everyone_users[0]; + i++; + + sid_name_map[i].sid = &global_sid_Creator_Owner_Domain; + sid_name_map[i].name = ""; + sid_name_map[i].known_users = &creator_owner_users[0]; + i++; + + sid_name_map[i].sid = &global_sid_NT_Authority; + sid_name_map[i].name = "NT Authority"; + sid_name_map[i].known_users = &nt_authority_users[0]; + i++; + + + /* end of array */ + sid_name_map[i].sid = NULL; + sid_name_map[i].name = NULL; + sid_name_map[i].known_users = NULL; + + sid_name_map_initialized = True; + + return; + +} + +/************************************************************************** + Turns a domain SID into a name, returned in the nt_domain argument. +***************************************************************************/ + +BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain) +{ + fstring sid_str; + int i = 0; + + sid_to_string(sid_str, sid); + + if (!sid_name_map_initialized) + init_sid_name_map(); + + DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str)); + + if (nt_domain == NULL) + return False; + + while (sid_name_map[i].sid != NULL) { + sid_to_string(sid_str, sid_name_map[i].sid); + DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str)); + if (sid_equal(sid_name_map[i].sid, sid)) { + fstrcpy(nt_domain, sid_name_map[i].name); + DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain)); + return True; + } + i++; + } + + DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str)); + + return False; +} + +/************************************************************************** + Looks up a known username from one of the known domains. +***************************************************************************/ + +BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) +{ + int i = 0; + struct sid_name_map_info *psnm; + + if (!sid_name_map_initialized) + init_sid_name_map(); + + for(i = 0; sid_name_map[i].sid != NULL; i++) { + psnm = &sid_name_map[i]; + if(sid_equal(psnm->sid, sid)) { + int j; + for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) { + if(rid == psnm->known_users[j].rid) { + DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n", + (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name )); + fstrcpy( name, psnm->known_users[j].known_user_name); + *psid_name_use = psnm->known_users[j].sid_name_use; + return True; + } + } + } + } + + return False; +} + +/************************************************************************** + Turns a domain name into a SID. + *** side-effect: if the domain name is NULL, it is set to our domain *** +***************************************************************************/ + +BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain) +{ + int i = 0; + + if (nt_domain == NULL) { + DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n")); + sid_copy(sid, get_global_sam_sid()); + return True; + } + + if (nt_domain[0] == 0) { + fstrcpy(nt_domain, global_myname); + DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain)); + sid_copy(sid, get_global_sam_sid()); + return True; + } + + DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain)); + + if (!sid_name_map_initialized) + init_sid_name_map(); + + while (sid_name_map[i].name != NULL) { + DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name)); + if (strequal(sid_name_map[i].name, nt_domain)) { + fstring sid_str; + sid_copy(sid, sid_name_map[i].sid); + sid_to_string(sid_str, sid_name_map[i].sid); + DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str)); + return True; + } + i++; + } + + DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain)); + return False; +} + +/***************************************************************** + Check if the SID is our domain SID (S-1-5-21-x-y-z). +*****************************************************************/ +BOOL sid_check_is_domain(const DOM_SID *sid) +{ + return sid_equal(sid, get_global_sam_sid()); +} + +/***************************************************************** + Check if the SID is our domain SID (S-1-5-21-x-y-z). +*****************************************************************/ +BOOL sid_check_is_in_our_domain(const DOM_SID *sid) +{ + DOM_SID dom_sid; + uint32 rid; + + sid_copy(&dom_sid, sid); + sid_split_rid(&dom_sid, &rid); + + return sid_equal(&dom_sid, get_global_sam_sid()); +} + diff --git a/source3/printing/notify.c b/source3/printing/notify.c new file mode 100644 index 0000000000..21e28d0ca7 --- /dev/null +++ b/source3/printing/notify.c @@ -0,0 +1,230 @@ +/* + Unix SMB/Netbios implementation. + Version 2.2 + printing backend routines + Copyright (C) Tim Potter, 2002 + + 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 "printing.h" + +/* + * Print notification routines + */ + +static void send_spoolss_notify2_msg(struct spoolss_notify_msg *msg) +{ + char *buf = NULL; + int buflen = 0, len; + TDB_CONTEXT *tdb; + + /* Let's not waste any time with this */ + + if (lp_disable_spoolss()) + return; + + /* Flatten data into a message */ + +again: + len = 0; + + /* Pack header */ + + len += tdb_pack(buf + len, buflen - len, "f", msg->printer); + + len += tdb_pack(buf + len, buflen - len, "ddddd", + msg->type, msg->field, msg->id, msg->len, msg->flags); + + /* Pack data */ + + if (msg->len == 0) + len += tdb_pack(buf + len, buflen - len, "dd", + msg->notify.value[0], msg->notify.value[1]); + else + len += tdb_pack(buf + len, buflen - len, "B", + msg->len, msg->notify.data); + + if (buflen != len) { + buf = Realloc(buf, len); + buflen = len; + goto again; + } + + /* Send message */ + + tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0); + + if (!tdb) { + DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n")); + return; + } + + message_send_all(tdb, MSG_PRINTER_NOTIFY2, buf, + buflen, False, NULL); + + SAFE_FREE(buf); + tdb_close(tdb); +} + +static void send_notify_field_values(const char *printer_name, uint32 type, + uint32 field, uint32 id, uint32 value1, + uint32 value2, uint32 flags) +{ + struct spoolss_notify_msg msg; + + ZERO_STRUCT(msg); + + fstrcpy(msg.printer, printer_name); + msg.type = type; + msg.field = field; + msg.id = id; + msg.notify.value[0] = value1; + msg.notify.value[1] = value2; + msg.flags = flags; + + send_spoolss_notify2_msg(&msg); +} + +static void send_notify_field_buffer(const char *printer_name, uint32 type, + uint32 field, uint32 id, uint32 len, + char *buffer) +{ + struct spoolss_notify_msg msg; + + ZERO_STRUCT(msg); + + fstrcpy(msg.printer, printer_name); + msg.type = type; + msg.field = field; + msg.id = id; + msg.len = len; + msg.notify.data = buffer; + + send_spoolss_notify2_msg(&msg); +} + +/* Send a message that the printer status has changed */ + +void notify_printer_status_byname(const char *printer_name, uint32 status) +{ + /* Printer status stored in value1 */ + + send_notify_field_values(printer_name, PRINTER_NOTIFY_TYPE, + PRINTER_NOTIFY_STATUS, 0, + status, 0, 0); +} + +void notify_printer_status(int snum, uint32 status) +{ + const char *printer_name = PRINTERNAME(snum); + + if (printer_name) + notify_printer_status_byname(printer_name, status); +} + +void notify_job_status_byname(const char *printer_name, uint32 jobid, uint32 status, + uint32 flags) +{ + /* Job id stored in id field, status in value1 */ + + send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, + JOB_NOTIFY_STATUS, jobid, + status, 0, flags); +} + +void notify_job_status(int snum, uint32 jobid, uint32 status) +{ + const char *printer_name = PRINTERNAME(snum); + + notify_job_status_byname(printer_name, jobid, status, 0); +} + +void notify_job_total_bytes(int snum, uint32 jobid, uint32 size) +{ + const char *printer_name = PRINTERNAME(snum); + + /* Job id stored in id field, status in value1 */ + + send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, + JOB_NOTIFY_TOTAL_BYTES, jobid, + size, 0, 0); +} + +void notify_job_total_pages(int snum, uint32 jobid, uint32 pages) +{ + const char *printer_name = PRINTERNAME(snum); + + /* Job id stored in id field, status in value1 */ + + send_notify_field_values(printer_name, JOB_NOTIFY_TYPE, + JOB_NOTIFY_TOTAL_PAGES, jobid, + pages, 0, 0); +} + +void notify_job_username(int snum, uint32 jobid, char *name) +{ + const char *printer_name = PRINTERNAME(snum); + + send_notify_field_buffer( + printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, + jobid, strlen(name) + 1, name); +} + +void notify_job_name(int snum, uint32 jobid, char *name) +{ + const char *printer_name = PRINTERNAME(snum); + + send_notify_field_buffer( + printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, + jobid, strlen(name) + 1, name); +} + +void notify_job_submitted(int snum, uint32 jobid, time_t submitted) +{ + const char *printer_name = PRINTERNAME(snum); + + send_notify_field_buffer( + printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, + jobid, sizeof(submitted), (char *)&submitted); +} + +void notify_printer_delete(char *printer_name) +{ +} + +void notify_printer_add(char *printer_name) +{ +} + +void notify_printer_driver(int num, char *driver_name) +{ +} + +void notify_printer_comment(int num, char *comment) +{ +} + +void notify_printer_sharename(int num, char *share_name) +{ +} + +void notify_printer_port(int num, char *port_name) +{ +} + +void notify_printer_location(int num, char *location) +{ +} diff --git a/source3/python/py_common.h b/source3/python/py_common.h new file mode 100644 index 0000000000..1f5188971d --- /dev/null +++ b/source3/python/py_common.h @@ -0,0 +1,35 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 _PY_COMMON_H +#define _PY_COMMON_H + +#include "includes.h" + +/* Return a cli_state struct opened on the specified pipe. If credentials + are passed use them. */ + +typedef struct cli_state *(cli_pipe_fn)( + struct cli_state *cli, char *system_name, + struct ntuser_creds *creds); + +#include "python/py_common_proto.h" + +#endif /* _PY_COMMON_H */ diff --git a/source3/python/py_lsa.h b/source3/python/py_lsa.h new file mode 100644 index 0000000000..f9a30d2f7e --- /dev/null +++ b/source3/python/py_lsa.h @@ -0,0 +1,46 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 _PY_LSA_H +#define _PY_LSA_H + +#include "includes.h" +#include "Python.h" + +#include "python/py_common_proto.h" + +/* LSA policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND pol; +} lsa_policy_hnd_object; + +/* Exceptions raised by this module */ + +extern PyTypeObject lsa_policy_hnd_type; + +extern PyObject *lsa_error; + +#include "python/py_lsa_proto.h" + +#endif /* _PY_LSA_H */ diff --git a/source3/python/py_lsa_proto.h b/source3/python/py_lsa_proto.h new file mode 100644 index 0000000000..1c6f6ab1d1 --- /dev/null +++ b/source3/python/py_lsa_proto.h @@ -0,0 +1,13 @@ +#ifndef _PY_LSA_PROTO_H +#define _PY_LSA_PROTO_H + +/* This file is automatically generated with "make proto". DO NOT EDIT */ + + +/* The following definitions come from python/py_lsa.c */ + +PyObject *new_lsa_policy_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol); +void initlsa(void); + +#endif /* _PY_LSA_PROTO_H */ diff --git a/source3/python/py_ntsec.c b/source3/python/py_ntsec.c new file mode 100644 index 0000000000..f216d96aa8 --- /dev/null +++ b/source3/python/py_ntsec.c @@ -0,0 +1,284 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 "Python.h" + +#include "python/py_common_proto.h" + +/* Convert a SID to a Python dict */ + +BOOL py_from_SID(PyObject **obj, DOM_SID *sid) +{ + fstring sidstr; + + if (!sid) { + Py_INCREF(Py_None); + *obj = Py_None; + return True; + } + + if (!sid_to_string(sidstr, sid)) + return False; + + *obj = PyString_FromString(sidstr); + + return True; +} + +BOOL py_to_SID(DOM_SID *sid, PyObject *obj) +{ + if (!PyString_Check(obj)) + return False; + + return string_to_sid(sid, PyString_AsString(obj)); +} + +BOOL py_from_ACE(PyObject **dict, SEC_ACE *ace) +{ + PyObject *obj; + + if (!ace) { + Py_INCREF(Py_None); + *dict = Py_None; + return True; + } + + *dict = PyDict_New(); + + PyDict_SetItemString(*dict, "type", PyInt_FromLong(ace->type)); + PyDict_SetItemString(*dict, "flags", PyInt_FromLong(ace->flags)); + PyDict_SetItemString(*dict, "mask", PyInt_FromLong(ace->info.mask)); + + if (py_from_SID(&obj, &ace->trustee)) + PyDict_SetItemString(*dict, "trustee", obj); + + return True; +} + +BOOL py_to_ACE(SEC_ACE *ace, PyObject *dict) +{ + PyObject *obj; + uint8 ace_type, ace_flags; + DOM_SID trustee; + SEC_ACCESS sec_access; + + if (!PyDict_Check(dict)) + return False; + + if (!(obj = PyDict_GetItemString(dict, "type")) || + !PyInt_Check(obj)) + return False; + + ace_type = PyInt_AsLong(obj); + + if (!(obj = PyDict_GetItemString(dict, "flags")) || + !PyInt_Check(obj)) + return False; + + ace_flags = PyInt_AsLong(obj); + + if (!(obj = PyDict_GetItemString(dict, "trustee")) || + !PyString_Check(obj)) + return False; + + if (!py_to_SID(&trustee, obj)) + return False; + + if (!(obj = PyDict_GetItemString(dict, "mask")) || + !PyInt_Check(obj)) + return False; + + sec_access.mask = PyInt_AsLong(obj); + + init_sec_ace(ace, &trustee, ace_type, sec_access, ace_flags); + + /* Fill in size field */ + + ace->size = SEC_ACE_HEADER_SIZE + sid_size(&trustee); + + return True; +} + +BOOL py_from_ACL(PyObject **dict, SEC_ACL *acl) +{ + PyObject *ace_list; + int i; + + if (!acl) { + Py_INCREF(Py_None); + *dict = Py_None; + return True; + } + + *dict = PyDict_New(); + + PyDict_SetItemString(*dict, "revision", PyInt_FromLong(acl->revision)); + + ace_list = PyList_New(acl->num_aces); + + for (i = 0; i < acl->num_aces; i++) { + PyObject *obj; + + if (py_from_ACE(&obj, &acl->ace[i])) + PyList_SetItem(ace_list, i, obj); + } + + PyDict_SetItemString(*dict, "ace_list", ace_list); + + return True; +} + +BOOL py_to_ACL(SEC_ACL *acl, PyObject *dict, TALLOC_CTX *mem_ctx) +{ + PyObject *obj; + uint32 i; + + if (!(obj = PyDict_GetItemString(dict, "revision")) || + !PyInt_Check(obj)) + return False; + + acl->revision = PyInt_AsLong(obj); + + if (!(obj = PyDict_GetItemString(dict, "ace_list")) || + !PyList_Check(obj)) + return False; + + acl->num_aces = PyList_Size(obj); + + acl->ace = talloc(mem_ctx, acl->num_aces * sizeof(SEC_ACE)); + acl->size = SEC_ACL_HEADER_SIZE; + + for (i = 0; i < acl->num_aces; i++) { + PyObject *py_ace = PyList_GetItem(obj, i); + + if (!py_to_ACE(&acl->ace[i], py_ace)) + return False; + + acl->size += acl->ace[i].size; + } + + return True; +} + +BOOL py_from_SECDESC(PyObject **dict, SEC_DESC *sd) +{ + PyObject *obj; + + *dict = PyDict_New(); + + PyDict_SetItemString(*dict, "revision", PyInt_FromLong(sd->revision)); + + if (py_from_SID(&obj, sd->owner_sid)) + PyDict_SetItemString(*dict, "owner_sid", obj); + + if (py_from_SID(&obj, sd->grp_sid)) + PyDict_SetItemString(*dict, "group_sid", obj); + + if (py_from_ACL(&obj, sd->dacl)) + PyDict_SetItemString(*dict, "dacl", obj); + + if (py_from_ACL(&obj, sd->sacl)) + PyDict_SetItemString(*dict, "sacl", obj); + + return True; +} + +BOOL py_to_SECDESC(SEC_DESC **sd, PyObject *dict, TALLOC_CTX *mem_ctx) +{ + PyObject *obj; + uint16 revision; + DOM_SID owner_sid, group_sid; + SEC_ACL sacl, dacl; + BOOL got_dacl = False, got_sacl = False; + BOOL got_owner_sid = False, got_group_sid = False; + + ZERO_STRUCT(dacl); ZERO_STRUCT(sacl); + ZERO_STRUCT(owner_sid); ZERO_STRUCT(group_sid); + + if (!(obj = PyDict_GetItemString(dict, "revision"))) + return False; + + revision = PyInt_AsLong(obj); + + if ((obj = PyDict_GetItemString(dict, "owner_sid"))) { + + if (obj != Py_None) { + + if (!py_to_SID(&owner_sid, obj)) + return False; + + got_owner_sid = True; + } + } + + if ((obj = PyDict_GetItemString(dict, "group_sid"))) { + + if (obj != Py_None) { + + if (!py_to_SID(&group_sid, obj)) + return False; + + got_group_sid = True; + } + } + + if ((obj = PyDict_GetItemString(dict, "dacl"))) { + + if (obj != Py_None) { + + if (!py_to_ACL(&dacl, obj, mem_ctx)) + return False; + + got_dacl = True; + } + } + + if ((obj = PyDict_GetItemString(dict, "sacl"))) { + + if (obj != Py_None) { + + if (!py_to_ACL(&sacl, obj, mem_ctx)) + return False; + + got_sacl = True; + } + } + +#if 0 /* For new secdesc code */ + *sd = make_sec_desc(mem_ctx, revision, + got_owner_sid ? &owner_sid : NULL, + got_group_sid ? &group_sid : NULL, + got_sacl ? &sacl : NULL, + got_dacl ? &dacl : NULL); +#else + { + size_t sd_size; + + *sd = make_sec_desc(mem_ctx, revision, + got_owner_sid ? &owner_sid : NULL, + got_group_sid ? &group_sid : NULL, + got_sacl ? &sacl : NULL, + got_dacl ? &dacl : NULL, &sd_size); + } +#endif + + return True; +} diff --git a/source3/python/py_samr.h b/source3/python/py_samr.h new file mode 100644 index 0000000000..22c3660ef9 --- /dev/null +++ b/source3/python/py_samr.h @@ -0,0 +1,83 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 _PY_SAMR_H +#define _PY_SAMR_H + +#include "includes.h" +#include "Python.h" + +#include "python/py_common_proto.h" + +/* SAMR connect policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND connect_pol; +} samr_connect_hnd_object; + +/* SAMR domain policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND domain_pol; +} samr_domain_hnd_object; + +/* SAMR user policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND user_pol; +} samr_user_hnd_object; + +/* SAMR group policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND group_pol; +} samr_group_hnd_object; + +/* SAMR alias policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND alias_pol; +} samr_alias_hnd_object; + +extern PyTypeObject samr_connect_hnd_type, samr_domain_hnd_type, + samr_user_hnd_type, samr_group_hnd_type, samr_alias_hnd_type; + +/* Exceptions raised by this module */ + +extern PyObject *samr_error; + +/* #include "python/py_samr_proto.h" */ + +#endif /* _PY_SAMR_H */ diff --git a/source3/python/py_spoolss.h b/source3/python/py_spoolss.h new file mode 100644 index 0000000000..40a6ae972e --- /dev/null +++ b/source3/python/py_spoolss.h @@ -0,0 +1,46 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 _PY_SPOOLSS_H +#define _PY_SPOOLSS_H + +#include "includes.h" +#include "Python.h" + +#include "python/py_common_proto.h" + +/* Spoolss policy handle object */ + +typedef struct { + PyObject_HEAD + struct cli_state *cli; + TALLOC_CTX *mem_ctx; + POLICY_HND pol; +} spoolss_policy_hnd_object; + +/* Exceptions raised by this module */ + +extern PyTypeObject spoolss_policy_hnd_type; + +extern PyObject *spoolss_error, *spoolss_werror; + +#include "python/py_spoolss_proto.h" + +#endif /* _PY_SPOOLSS_H */ diff --git a/source3/python/py_spoolss_forms_conv.c b/source3/python/py_spoolss_forms_conv.c new file mode 100644 index 0000000000..6ef953cbc9 --- /dev/null +++ b/source3/python/py_spoolss_forms_conv.c @@ -0,0 +1,79 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 "python/py_spoolss.h" +#include "python/py_conv.h" + +struct pyconv py_FORM[] = { + { "flags", PY_UINT32, offsetof(FORM, flags) }, + { "width", PY_UINT32, offsetof(FORM, size_x) }, + { "length", PY_UINT32, offsetof(FORM, size_y) }, + { "top", PY_UINT32, offsetof(FORM, top) }, + { "left", PY_UINT32, offsetof(FORM, left) }, + { "right", PY_UINT32, offsetof(FORM, right) }, + { "bottom", PY_UINT32, offsetof(FORM, bottom) }, + { NULL } +}; + +struct pyconv py_FORM_1[] = { + { "flags", PY_UINT32, offsetof(FORM_1, flag) }, + { "width", PY_UINT32, offsetof(FORM_1, width) }, + { "length", PY_UINT32, offsetof(FORM_1, length) }, + { "top", PY_UINT32, offsetof(FORM_1, top) }, + { "left", PY_UINT32, offsetof(FORM_1, left) }, + { "right", PY_UINT32, offsetof(FORM_1, right) }, + { "bottom", PY_UINT32, offsetof(FORM_1, bottom) }, + { "name", PY_UNISTR, offsetof(FORM_1, name) }, + { NULL } +}; + +BOOL py_from_FORM_1(PyObject **dict, FORM_1 *form) +{ + *dict = from_struct(form, py_FORM_1); + + PyDict_SetItemString(*dict, "level", PyInt_FromLong(1)); + + return True; +} + +BOOL py_to_FORM(FORM *form, PyObject *dict) +{ + PyObject *obj, *dict_copy = PyDict_Copy(dict); + char *name; + + obj = PyDict_GetItemString(dict, "name"); + + if (!obj || !PyString_Check(obj)) + return False; + + PyDict_DelItemString(dict_copy, "level"); + PyDict_DelItemString(dict_copy, "name"); + + if (!to_struct(form, dict_copy, py_FORM)) { + Py_DECREF(dict_copy); + return False; + } + + name = PyString_AsString(obj); + + init_unistr2(&form->name, name, strlen(name) + 1); + + return True; +} diff --git a/source3/python/py_spoolss_jobs_conv.c b/source3/python/py_spoolss_jobs_conv.c new file mode 100644 index 0000000000..cb04ec6713 --- /dev/null +++ b/source3/python/py_spoolss_jobs_conv.c @@ -0,0 +1,102 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 "python/py_spoolss.h" +#include "python/py_conv.h" + +struct pyconv py_JOB_INFO_1[] = { + { "jobid", PY_UINT32, offsetof(JOB_INFO_1, jobid) }, + { "printer_name", PY_UNISTR, offsetof(JOB_INFO_1, printername) }, + { "server_name", PY_UNISTR, offsetof(JOB_INFO_1, machinename) }, + { "user_name", PY_UNISTR, offsetof(JOB_INFO_1, username) }, + { "document_name", PY_UNISTR, offsetof(JOB_INFO_1, document) }, + { "data_type", PY_UNISTR, offsetof(JOB_INFO_1, datatype) }, + { "text_status", PY_UNISTR, offsetof(JOB_INFO_1, text_status) }, + { "status", PY_UINT32, offsetof(JOB_INFO_1, status) }, + { "priority", PY_UINT32, offsetof(JOB_INFO_1, priority) }, + { "position", PY_UINT32, offsetof(JOB_INFO_1, position) }, + { "total_pages", PY_UINT32, offsetof(JOB_INFO_1, totalpages) }, + { "pages_printed", PY_UINT32, offsetof(JOB_INFO_1, pagesprinted) }, + { NULL } +}; + +struct pyconv py_JOB_INFO_2[] = { + { "jobid", PY_UINT32, offsetof(JOB_INFO_2, jobid) }, + { "printer_name", PY_UNISTR, offsetof(JOB_INFO_2, printername) }, + { "server_name", PY_UNISTR, offsetof(JOB_INFO_2, machinename) }, + { "user_name", PY_UNISTR, offsetof(JOB_INFO_2, username) }, + { "document_name", PY_UNISTR, offsetof(JOB_INFO_2, document) }, + { "notify_name", PY_UNISTR, offsetof(JOB_INFO_2, notifyname) }, + { "data_type", PY_UNISTR, offsetof(JOB_INFO_2, datatype) }, + { "print_processor", PY_UNISTR, offsetof(JOB_INFO_2, printprocessor) }, + { "parameters", PY_UNISTR, offsetof(JOB_INFO_2, parameters) }, + { "driver_name", PY_UNISTR, offsetof(JOB_INFO_2, drivername) }, + { "text_status", PY_UNISTR, offsetof(JOB_INFO_2, text_status) }, + { "status", PY_UINT32, offsetof(JOB_INFO_2, status) }, + { "priority", PY_UINT32, offsetof(JOB_INFO_2, priority) }, + { "position", PY_UINT32, offsetof(JOB_INFO_2, position) }, + { "start_time", PY_UINT32, offsetof(JOB_INFO_2, starttime) }, + { "until_time", PY_UINT32, offsetof(JOB_INFO_2, untiltime) }, + { "total_pages", PY_UINT32, offsetof(JOB_INFO_2, totalpages) }, + { "size", PY_UINT32, offsetof(JOB_INFO_2, size) }, + { "time_elapsed", PY_UINT32, offsetof(JOB_INFO_2, timeelapsed) }, + { "pages_printed", PY_UINT32, offsetof(JOB_INFO_2, pagesprinted) }, + { NULL } +}; + +struct pyconv py_DOC_INFO_1[] = { + { "document_name", PY_UNISTR, offsetof(DOC_INFO_1, docname) }, + { "output_file", PY_UNISTR, offsetof(DOC_INFO_1, outputfile) }, + { "data_type", PY_UNISTR, offsetof(DOC_INFO_1, datatype) }, + { NULL } +}; + +BOOL py_from_JOB_INFO_1(PyObject **dict, JOB_INFO_1 *info) +{ + *dict = from_struct(info, py_JOB_INFO_1); + return True; +} + +BOOL py_to_JOB_INFO_1(JOB_INFO_1 *info, PyObject *dict) +{ + return False; +} + +BOOL py_from_JOB_INFO_2(PyObject **dict, JOB_INFO_2 *info) +{ + *dict = from_struct(info, py_JOB_INFO_2); + return True; +} + +BOOL py_to_JOB_INFO_2(JOB_INFO_2 *info, PyObject *dict) +{ + return False; +} + +BOOL py_from_DOC_INFO_1(PyObject **dict, DOC_INFO_1 *info) +{ + *dict = from_struct(info, py_DOC_INFO_1); + return True; +} + +BOOL py_to_DOC_INFO_1(DOC_INFO_1 *info, PyObject *dict) +{ + return to_struct(info, dict, py_DOC_INFO_1); +} diff --git a/source3/python/py_spoolss_ports.c b/source3/python/py_spoolss_ports.c new file mode 100644 index 0000000000..b5f2102e5e --- /dev/null +++ b/source3/python/py_spoolss_ports.c @@ -0,0 +1,137 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 "python/py_spoolss.h" + +/* Enumerate ports */ + +PyObject *spoolss_enumports(PyObject *self, PyObject *args, PyObject *kw) +{ + WERROR werror; + PyObject *result = NULL, *creds = NULL; + int level = 1; + uint32 i, needed, num_ports; + static char *kwlist[] = {"server", "level", "creds", NULL}; + TALLOC_CTX *mem_ctx = NULL; + struct cli_state *cli = NULL; + char *server, *errstr; + PORT_INFO_CTR ctr; + + /* Parse parameters */ + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "s|iO", kwlist, &server, &level, &creds)) + return NULL; + + if (server[0] != '\\' || server[1] != '\\') { + PyErr_SetString(PyExc_ValueError, "UNC name required"); + return NULL; + } + + server += 2; + + if (creds && creds != Py_None && !PyDict_Check(creds)) { + PyErr_SetString(PyExc_TypeError, + "credentials must be dictionary or None"); + return NULL; + } + + if (!(cli = open_pipe_creds(server, creds, PIPE_SPOOLSS, &errstr))) { + PyErr_SetString(spoolss_error, errstr); + free(errstr); + goto done; + } + + if (!(mem_ctx = talloc_init())) { + PyErr_SetString( + spoolss_error, "unable to init talloc context\n"); + goto done; + } + + /* Call rpc function */ + + werror = cli_spoolss_enum_ports( + cli, mem_ctx, 0, &needed, level, &num_ports, &ctr); + + if (W_ERROR_V(werror) == ERRinsufficientbuffer) + werror = cli_spoolss_enum_ports( + cli, mem_ctx, needed, NULL, level, + &num_ports, &ctr); + + if (!W_ERROR_IS_OK(werror)) { + PyErr_SetObject(spoolss_werror, py_werror_tuple(werror)); + goto done; + } + + /* Return value */ + + switch (level) { + case 1: + result = PyDict_New(); + + for (i = 0; i < num_ports; i++) { + PyObject *value; + fstring name; + + rpcstr_pull(name, ctr.port.info_1[i].port_name.buffer, + sizeof(fstring), -1, STR_TERMINATE); + + py_from_PORT_INFO_1(&value, &ctr.port.info_1[i]); + + PyDict_SetItemString( + value, "level", PyInt_FromLong(1)); + + PyDict_SetItemString(result, name, value); + } + + break; + case 2: + result = PyDict_New(); + + for(i = 0; i < num_ports; i++) { + PyObject *value; + fstring name; + + rpcstr_pull(name, ctr.port.info_2[i].port_name.buffer, + sizeof(fstring), -1, STR_TERMINATE); + + py_from_PORT_INFO_2(&value, &ctr.port.info_2[i]); + + PyDict_SetItemString( + value, "level", PyInt_FromLong(2)); + + PyDict_SetItemString(result, name, value); + } + + break; + default: + PyErr_SetString(spoolss_error, "unknown info level"); + goto done; + } + + done: + if (cli) + cli_shutdown(cli); + + if (mem_ctx) + talloc_destroy(mem_ctx); + + return result; +} diff --git a/source3/python/py_tdb.c b/source3/python/py_tdb.c new file mode 100644 index 0000000000..4969c1047e --- /dev/null +++ b/source3/python/py_tdb.c @@ -0,0 +1,614 @@ +/* + Python wrappers for TDB module + + Copyright (C) Tim Potter, 2002 + + 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. +*/ + +/* + NOTE: Since tdb is licenced under the GPL any program that uses these bindings + must be distributed under the GPL license terms since this is what + the GPL requires. + + http://www.gnu.org/licenses/gpl-faq.html#IfInterpreterIsGPL +*/ + +#include "includes.h" +#include "Python.h" + +/* Tdb exception */ + +PyObject *py_tdb_error; + +/* tdb handle object */ + +typedef struct { + PyObject_HEAD + TDB_CONTEXT *tdb; +} tdb_hnd_object; + +PyTypeObject tdb_hnd_type; + +PyObject *new_tdb_hnd_object(TDB_CONTEXT *tdb) +{ + tdb_hnd_object *obj; + + obj = PyObject_New(tdb_hnd_object, &tdb_hnd_type); + obj->tdb = tdb; + + return (PyObject *)obj; +} + +PyObject *py_tdb_close(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj; + + if (!PyArg_ParseTuple(args, "O!", &tdb_hnd_type, &obj)) + return NULL; + + if (tdb_close(obj->tdb) == -1) { + obj->tdb = NULL; + PyErr_SetString(py_tdb_error, strerror(errno)); + return NULL; + } + + obj->tdb = NULL; + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject *py_tdb_open(PyObject *self, PyObject *args, PyObject *kw) +{ + static char *kwlist[] = { "name", "hash_size", "tdb_flags", + "open_flags", "mode", NULL }; + char *name; + int hash_size = 0, flags = TDB_DEFAULT, open_flags = -1, open_mode = 0600; + TDB_CONTEXT *tdb; + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "s|iiii", kwlist, &name, &hash_size, &flags, + &open_flags, &open_mode)) + return NULL; + + /* Default open_flags to read/write */ + + if (open_flags == -1) { + if (access(name, W_OK) == -1) + open_flags = O_RDONLY; + else + open_flags = O_RDWR; + } + + if (!(tdb = tdb_open(name, hash_size, flags, open_flags, open_mode))) { + PyErr_SetString(py_tdb_error, strerror(errno)); + return NULL; + } + + return new_tdb_hnd_object(tdb); +} + +/* + * Allow a tdb to act as a python mapping (dictionary) + */ + +static int tdb_traverse_count(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, + void *state) +{ + /* Do nothing - tdb_traverse will return the number of records + traversed. */ + + return 0; +} + +static int tdb_hnd_length(tdb_hnd_object *obj) +{ + int result; + + result = tdb_traverse(obj->tdb, tdb_traverse_count, NULL); + + return result; +} + +static PyObject *tdb_hnd_subscript(tdb_hnd_object *obj, PyObject *key) +{ + TDB_DATA drec, krec; + PyObject *result; + + if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) + return NULL; + + drec = tdb_fetch(obj->tdb, krec); + + if (!drec.dptr) { + PyErr_SetString(PyExc_KeyError, + PyString_AsString(key)); + return NULL; + } + + result = PyString_FromStringAndSize(drec.dptr, drec.dsize); + free(drec.dptr); + + return result; +} + +static int tdb_ass_subscript(tdb_hnd_object *obj, PyObject *key, PyObject *value) +{ + TDB_DATA krec, drec; + + if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize)) { + PyErr_SetString(PyExc_TypeError, + "tdb mappings have string indices only"); + return -1; + } + + if (!obj->tdb) { + PyErr_SetString( + py_tdb_error, "tdb object has been closed"); + return -1; + } + + if (!value) { + + /* Delete value */ + + if (tdb_delete(obj->tdb, krec) == -1) { + PyErr_SetString(PyExc_KeyError, + PyString_AsString(value)); + return -1; + } + + } else { + + /* Set value */ + + if (!PyArg_Parse(value, "s#", &drec.dptr, &drec.dsize)) { + PyErr_SetString(PyExc_TypeError, + "tdb mappings have string elements only"); + return -1; + } + + errno = 0; + + if (tdb_store(obj->tdb, krec, drec, 0) < 0 ) { + if (errno != 0) + PyErr_SetFromErrno(py_tdb_error); + else + PyErr_SetString( + py_tdb_error, + (char *)tdb_errorstr(obj->tdb)); + + return -1; + } + } + + return 0; +} + +static PyMappingMethods tdb_mapping = { + (inquiry) tdb_hnd_length, + (binaryfunc) tdb_hnd_subscript, + (objobjargproc) tdb_ass_subscript +}; + +/* + * Utility methods + */ + +/* Return non-zero if a given key exists in the tdb */ + +PyObject *py_tdb_hnd_has_key(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + TDB_DATA key; + + if (!PyArg_ParseTuple(args, "s#", &key.dptr, &key.dsize)) + return NULL; + + if (!obj->tdb) { + PyErr_SetString( + py_tdb_error, "tdb object has been closed"); + return NULL; + } + + return PyInt_FromLong(tdb_exists(obj->tdb, key)); +} + +/* Return a list of keys in the tdb */ + +static int tdb_traverse_keys(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, + void *state) +{ + PyObject *key_list = (PyObject *)state; + + PyList_Append(key_list, + PyString_FromStringAndSize(key.dptr, key.dsize)); + + return 0; +} + +PyObject *py_tdb_hnd_keys(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + PyObject *key_list = PyList_New(0); + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + if (tdb_traverse(obj->tdb, tdb_traverse_keys, key_list) == -1) { + PyErr_SetString(py_tdb_error, "error traversing tdb"); + Py_DECREF(key_list); + return NULL; + } + + return key_list; +} + +PyObject *py_tdb_hnd_first_key(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + TDB_DATA key; + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + key = tdb_firstkey(obj->tdb); + + return Py_BuildValue("s#", key.dptr, key.dsize); +} + +PyObject *py_tdb_hnd_next_key(PyObject *self, PyObject *py_oldkey) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + TDB_DATA key, oldkey; + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + if (!PyArg_Parse(py_oldkey, "s#", &oldkey.dptr, &oldkey.dsize)) + return NULL; + + key = tdb_nextkey(obj->tdb, oldkey); + + return Py_BuildValue("s#", key.dptr, key.dsize); +} + +/* + * Locking routines + */ + +PyObject *py_tdb_hnd_lock_all(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + int result; + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + result = tdb_lockall(obj->tdb); + + return PyInt_FromLong(result != -1); +} + +PyObject *py_tdb_hnd_unlock_all(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + tdb_unlockall(obj->tdb); + + Py_INCREF(Py_None); + return Py_None; +} + +/* Return an array of keys from a python object which must be a string or a + list of strings. */ + +static BOOL make_lock_list(PyObject *py_keys, TDB_DATA **keys, int *num_keys) +{ + /* Are we a list or a string? */ + + if (!PyList_Check(py_keys) && !PyString_Check(py_keys)) { + PyErr_SetString(PyExc_TypeError, "arg must be list of string"); + return False; + } + + if (PyList_Check(py_keys)) { + int i; + + /* Turn python list into array of keys */ + + *num_keys = PyList_Size(py_keys); + *keys = (TDB_DATA *)malloc(sizeof(TDB_DATA) * (*num_keys)); + + for (i = 0; i < *num_keys; i++) { + PyObject *key = PyList_GetItem(py_keys, i); + + if (!PyString_Check(key)) { + PyErr_SetString( + PyExc_TypeError, + "list elements must be strings"); + return False; + } + + PyArg_Parse(key, "s#", &(*keys)[i].dptr, + &(*keys)[i].dsize); + } + + } else { + + /* Turn python string into a single key */ + + *keys = (TDB_DATA *)malloc(sizeof(TDB_DATA)); + *num_keys = 1; + PyArg_Parse(py_keys, "s#", &(*keys)->dptr, &(*keys)->dsize); + } + + return True; +} + +PyObject *py_tdb_hnd_lock(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + PyObject *py_keys; + TDB_DATA *keys; + int num_keys, result; + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "O", &py_keys)) + return NULL; + + if (!make_lock_list(py_keys, &keys, &num_keys)) + return NULL; + + result = tdb_lockkeys(obj->tdb, num_keys, keys); + + free(keys); + + return PyInt_FromLong(result != -1); +} + +PyObject *py_tdb_hnd_unlock(PyObject *self, PyObject *args) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + + if (!obj->tdb) { + PyErr_SetString(py_tdb_error, "tdb object has been closed"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "")) + return NULL; + + tdb_unlockkeys(obj->tdb); + + Py_INCREF(Py_None); + return Py_None; +} + +/* + * tdb traversal + */ + +struct traverse_info { + PyObject *callback; + PyObject *state; +}; + +static int tdb_traverse_traverse(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA value, + void *state) +{ + struct traverse_info *info = state; + PyObject *arglist, *py_result; + int result; + + arglist = Py_BuildValue("(s#s#O)", key.dptr, key.dsize, value.dptr, + value.dsize, info->state); + + py_result = PyEval_CallObject(info->callback, arglist); + + Py_DECREF(arglist); + + if (!PyInt_Check(py_result)) { + result = 1; /* Hmm - non-integer object returned by callback */ + goto done; + } + + result = PyInt_AsLong(py_result); + +done: + Py_DECREF(py_result); + return result; +} + +PyObject *py_tdb_hnd_traverse(PyObject *self, PyObject *args, PyObject *kw) +{ + tdb_hnd_object *obj = (tdb_hnd_object *)self; + static char *kwlist[] = { "traverse_fn", "state", NULL }; + PyObject *state = Py_None, *callback; + struct traverse_info info; + int result; + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "O|O", kwlist, &callback, &state)) + return NULL; + + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_TypeError, "parameter must be callable"); + return NULL; + } + + Py_INCREF(callback); + Py_INCREF(state); + + info.callback = callback; + info.state = state; + + result = tdb_traverse(obj->tdb, tdb_traverse_traverse, &info); + + Py_DECREF(callback); + Py_DECREF(state); + + return PyInt_FromLong(result); +} + +/* + * Method dispatch table for this module + */ + +static PyMethodDef tdb_methods[] = { + { "open", (PyCFunction)py_tdb_open, METH_VARARGS | METH_KEYWORDS }, + { "close", (PyCFunction)py_tdb_close, METH_VARARGS }, + { NULL } +}; + +/* + * Methods on a tdb object + */ + +static PyMethodDef tdb_hnd_methods[] = { + { "keys", (PyCFunction)py_tdb_hnd_keys, METH_VARARGS }, + { "has_key", (PyCFunction)py_tdb_hnd_has_key, METH_VARARGS }, + { "first_key", (PyCFunction)py_tdb_hnd_first_key, METH_VARARGS }, + { "next_key", (PyCFunction)py_tdb_hnd_next_key, METH_VARARGS }, + { "lock_all", (PyCFunction)py_tdb_hnd_lock_all, METH_VARARGS }, + { "unlock_all", (PyCFunction)py_tdb_hnd_unlock_all, METH_VARARGS }, + { "lock", (PyCFunction)py_tdb_hnd_lock, METH_VARARGS }, + { "unlock", (PyCFunction)py_tdb_hnd_unlock, METH_VARARGS }, + { "traverse", (PyCFunction)py_tdb_hnd_traverse, METH_VARARGS | METH_KEYWORDS }, + { NULL } +}; + +/* Deallocate a tdb handle object */ + +static void tdb_hnd_dealloc(PyObject* self) +{ + tdb_hnd_object *hnd = (tdb_hnd_object *)self; + + if (hnd->tdb) { + tdb_close(hnd->tdb); + hnd->tdb = NULL; + } +} + +/* Return tdb handle attributes */ + +static PyObject *tdb_hnd_getattr(PyObject *self, char *attrname) +{ + return Py_FindMethod(tdb_hnd_methods, self, attrname); +} + +static char tdb_hnd_type_doc[] = +"Python wrapper for tdb."; + +PyTypeObject tdb_hnd_type = { + PyObject_HEAD_INIT(NULL) + 0, + "tdb", + sizeof(tdb_hnd_object), + 0, + tdb_hnd_dealloc, /* tp_dealloc*/ + 0, /* tp_print*/ + tdb_hnd_getattr, /* tp_getattr*/ + 0, /* tp_setattr*/ + 0, /* tp_compare*/ + 0, /* tp_repr*/ + 0, /* tp_as_number*/ + 0, /* tp_as_sequence*/ + &tdb_mapping, /* tp_as_mapping*/ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + tdb_hnd_type_doc, /* tp_doc */ +}; + +/* Constants */ + +static struct const_vals { + char *name; + uint32 value; +} module_const_vals[] = { + + /* Flags for tdb_open() */ + + { "TDB_DEFAULT", TDB_DEFAULT }, + { "TDB_CLEAR_IF_FIRST", TDB_CLEAR_IF_FIRST }, + { "TDB_INTERNAL", TDB_INTERNAL }, + { "TDB_NOLOCK", TDB_NOLOCK }, + { "TDB_NOMMAP", TDB_NOMMAP }, + { "TDB_CONVERT", TDB_CONVERT }, + { "TDB_BIGENDIAN", TDB_BIGENDIAN }, + + { NULL }, +}; + +static void const_init(PyObject *dict) +{ + struct const_vals *tmp; + PyObject *obj; + + for (tmp = module_const_vals; tmp->name; tmp++) { + obj = PyInt_FromLong(tmp->value); + PyDict_SetItemString(dict, tmp->name, obj); + Py_DECREF(obj); + } +} + +/* Module initialisation */ + +void inittdb(void) +{ + PyObject *module, *dict; + + /* Initialise module */ + + module = Py_InitModule("tdb", tdb_methods); + dict = PyModule_GetDict(module); + + py_tdb_error = PyErr_NewException("tdb.error", NULL, NULL); + PyDict_SetItemString(dict, "error", py_tdb_error); + + /* Initialise policy handle object */ + + tdb_hnd_type.ob_type = &PyType_Type; + + PyDict_SetItemString(dict, "tdb.hnd", + (PyObject *)&tdb_hnd_type); + + /* Initialise constants */ + + const_init(dict); +} diff --git a/source3/python/py_tdb.h b/source3/python/py_tdb.h new file mode 100644 index 0000000000..794a20cf2b --- /dev/null +++ b/source3/python/py_tdb.h @@ -0,0 +1,29 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 _PY_TDB_H +#define _PY_TDB_H + +#include "includes.h" +#include "Python.h" + +#include "python/py_common_proto.h" + +#endif /* _PY_TDB_H */ diff --git a/source3/python/py_winreg.c b/source3/python/py_winreg.c new file mode 100644 index 0000000000..ce27f5c533 --- /dev/null +++ b/source3/python/py_winreg.c @@ -0,0 +1,82 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 "python/py_winreg.h" + +static struct const_vals { + char *name; + uint32 value; +} module_const_vals[] = { + + /* Registry value types */ + + { "REG_NONE", REG_NONE }, + { "REG_SZ", REG_SZ }, + { "REG_EXPAND_SZ", REG_EXPAND_SZ }, + { "REG_BINARY", REG_BINARY }, + { "REG_DWORD", REG_DWORD }, + { "REG_DWORD_LE", REG_DWORD_LE }, + { "REG_DWORD_BE", REG_DWORD_BE }, + { "REG_LINK", REG_LINK }, + { "REG_MULTI_SZ", REG_MULTI_SZ }, + { "REG_RESOURCE_LIST", REG_RESOURCE_LIST }, + { "REG_FULL_RESOURCE_DESCRIPTOR", REG_FULL_RESOURCE_DESCRIPTOR }, + { "REG_RESOURCE_REQUIREMENTS_LIST", REG_RESOURCE_REQUIREMENTS_LIST }, + + { NULL }, +}; + +static void const_init(PyObject *dict) +{ + struct const_vals *tmp; + PyObject *obj; + + for (tmp = module_const_vals; tmp->name; tmp++) { + obj = PyInt_FromLong(tmp->value); + PyDict_SetItemString(dict, tmp->name, obj); + Py_DECREF(obj); + } +} + +/* + * Module initialisation + */ + +static PyMethodDef winreg_methods[] = { + { NULL } +}; + +void initwinreg(void) +{ + PyObject *module, *dict; + + /* Initialise module */ + + module = Py_InitModule("winreg", winreg_methods); + dict = PyModule_GetDict(module); + + /* Initialise constants */ + + const_init(dict); + + /* Do samba initialisation */ + + py_samba_init(); +} diff --git a/source3/python/py_winreg.h b/source3/python/py_winreg.h new file mode 100644 index 0000000000..088be724e2 --- /dev/null +++ b/source3/python/py_winreg.h @@ -0,0 +1,29 @@ +/* + Python wrappers for DCERPC/SMB client routines. + + Copyright (C) Tim Potter, 2002 + + 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 _PY_WINREG_H +#define _PY_WINREG_H + +#include "includes.h" +#include "Python.h" + +#include "python/py_common_proto.h" + +#endif /* _PY_WINREG_H */ diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c new file mode 100644 index 0000000000..7a5b1e5f46 --- /dev/null +++ b/source3/rpc_server/srv_samr_util.c @@ -0,0 +1,143 @@ +/* + Unix SMB/CIFS implementation. + SAMR Pipe utility functions. + Copyright (C) Jeremy Allison 1996-2001 + Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + Copyright (C) Gerald (Jerry) Carter 2000-2001 + Copyright (C) Andrew Bartlett 2001-2002 + + 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/************************************************************* + Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT + **************************************************************/ + +void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) +{ + + if (from == NULL || to == NULL) + return; + + pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True); + pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True); + pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True); + pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True); + pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True); + + pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); + + if (from->uni_user_name.buffer) + pdb_set_username(to , pdb_unistr2_convert(&from->uni_user_name )); + if (from->uni_full_name.buffer) + pdb_set_fullname(to , pdb_unistr2_convert(&from->uni_full_name )); + if (from->uni_home_dir.buffer) + pdb_set_homedir(to , pdb_unistr2_convert(&from->uni_home_dir ), True); + if (from->uni_dir_drive.buffer) + pdb_set_dir_drive(to , pdb_unistr2_convert(&from->uni_dir_drive ), True); + if (from->uni_logon_script.buffer) + pdb_set_logon_script(to , pdb_unistr2_convert(&from->uni_logon_script), True); + if (from->uni_profile_path.buffer) + pdb_set_profile_path(to , pdb_unistr2_convert(&from->uni_profile_path), True); + if (from->uni_acct_desc.buffer) + pdb_set_acct_desc(to , pdb_unistr2_convert(&from->uni_acct_desc )); + if (from->uni_workstations.buffer) + pdb_set_workstations(to , pdb_unistr2_convert(&from->uni_workstations)); + if (from->uni_unknown_str.buffer) + pdb_set_unknown_str(to , pdb_unistr2_convert(&from->uni_unknown_str )); + if (from->uni_munged_dial.buffer) + pdb_set_munged_dial(to , pdb_unistr2_convert(&from->uni_munged_dial )); + + if (from->user_rid) + pdb_set_user_sid_from_rid(to, from->user_rid); + if (from->group_rid) + pdb_set_group_sid_from_rid(to, from->group_rid); + + pdb_set_acct_ctrl(to, from->acb_info); + pdb_set_unknown_3(to, from->unknown_3); + + pdb_set_logon_divs(to, from->logon_divs); + pdb_set_hours_len(to, from->logon_hrs.len); + pdb_set_hours(to, from->logon_hrs.hours); + + pdb_set_unknown_5(to, from->unknown_5); + pdb_set_unknown_6(to, from->unknown_6); +} + + +/************************************************************* + Copies a sam passwd. + **************************************************************/ + +void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) +{ + if (from == NULL || to == NULL) + return; + + pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True); + pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True); + pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True); + pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True); + pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True); + + pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); + + if (from->uni_user_name.buffer) + pdb_set_username(to , pdb_unistr2_convert(&from->uni_user_name )); + if (from->uni_full_name.buffer) + pdb_set_fullname(to , pdb_unistr2_convert(&from->uni_full_name )); + if (from->uni_home_dir.buffer) + pdb_set_homedir(to , pdb_unistr2_convert(&from->uni_home_dir ), True); + if (from->uni_dir_drive.buffer) + pdb_set_dir_drive(to , pdb_unistr2_convert(&from->uni_dir_drive ), True); + if (from->uni_logon_script.buffer) + pdb_set_logon_script(to , pdb_unistr2_convert(&from->uni_logon_script), True); + if (from->uni_profile_path.buffer) + pdb_set_profile_path(to , pdb_unistr2_convert(&from->uni_profile_path), True); + if (from->uni_acct_desc.buffer) + pdb_set_acct_desc(to , pdb_unistr2_convert(&from->uni_acct_desc )); + if (from->uni_workstations.buffer) + pdb_set_workstations(to , pdb_unistr2_convert(&from->uni_workstations)); + if (from->uni_unknown_str.buffer) + pdb_set_unknown_str(to , pdb_unistr2_convert(&from->uni_unknown_str )); + if (from->uni_munged_dial.buffer) + pdb_set_munged_dial(to , pdb_unistr2_convert(&from->uni_munged_dial )); + + if (from->user_rid) + pdb_set_user_sid_from_rid(to, from->user_rid); + if (from->group_rid) + pdb_set_group_sid_from_rid(to, from->group_rid); + + /* FIXME!! Do we need to copy the passwords here as well? + I don't know. Need to figure this out --jerry */ + + /* Passwords dealt with in caller --abartlet */ + + pdb_set_acct_ctrl(to, from->acb_info); + pdb_set_unknown_3(to, from->unknown_3); + + pdb_set_logon_divs(to, from->logon_divs); + pdb_set_hours_len(to, from->logon_hrs.len); + pdb_set_hours(to, from->logon_hrs.hours); + + pdb_set_unknown_5(to, from->unknown_5); + pdb_set_unknown_6(to, from->unknown_6); +} + diff --git a/source3/script/findsmb.in b/source3/script/findsmb.in new file mode 100755 index 0000000000..d2aa94591b --- /dev/null +++ b/source3/script/findsmb.in @@ -0,0 +1,145 @@ +#!/usr/bin/perl +# +# Prints info on all smb responding machines on a subnet. +# This script needs to be run on a machine without nmbd running and be +# run as root to get correct info from WIN95 clients. +# +# syntax: +# findsmb [subnet broadcast address] +# +# with no agrument it will list machines on the current subnet +# +# There will be a "+" in front of the workgroup name for machines that are +# local master browsers for that workgroup. There will be an "*" in front +# of the workgroup name for machines that are the domain master browser for +# that workgroup. +# + +$SAMBABIN = "@prefix@/bin"; + +for ($i = 0; $i < 2; $i++) { # test for -d option and broadcast address + $_ = shift; + if (m/-d|-D/) { + $DEBUG = 1; + } else { + if ($_) { + $BCAST = "-B $_"; + } + } +} + +sub ipsort # do numeric sort on last field of IP address +{ + @t1 = split(/\./,$a); + @t2 = split(/\./,$b); + @t1[3] <=> @t2[3]; +} + +# look for all machines that respond to a name lookup + +open(NMBLOOKUP,"$SAMBABIN/nmblookup $BCAST '*'|") || + die("Can't run nmblookup '*'.\n"); + +# get rid of all lines that are not a response IP address, +# strip everything but IP address and sort by last field in address + +@ipaddrs = sort ipsort grep(s/ \*<00>.*$//,<NMBLOOKUP>); + +# print header info + +print "\nIP ADDR NETBIOS NAME WORKGROUP/OS/VERSION $BCAST\n"; +print "---------------------------------------------------------------------\n"; + +foreach $ip (@ipaddrs) # loop through each IP address found +{ + $ip =~ s/\n//; # strip newline from IP address + +# find the netbios names registered by each machine + + open(NMBLOOKUP,"$SAMBABIN/nmblookup -r -A $ip|") || + die("Can't get nmb name list.\n"); + @nmblookup = <NMBLOOKUP>; + close NMBLOOKUP; + +# get the first <00> name + + @name = grep(/<00>/,@nmblookup); + $_ = @name[0]; + if ($_) { # we have a netbios name + if (/GROUP/) { # is it a group name + ($name, $aliases, $type, $length, @addresses) = + gethostbyaddr(pack('C4',split('\.',$ip)),2); + if (! $name) { # could not get name + $name = "unknown nis name"; + } + } else { +# The Netbios name can contain lot of characters also '<' '>' +# and spaces. The follwing cure inside name space but not +# names starting or ending with spaces + /(.{1,15})\s+<00>\s+/; + $name = $1; + } + +# do an smbclient command on the netbios name. + + open(SMB,"$SAMBABIN/smbclient -N -L $name -I $ip -U% |") || + die("Can't do smbclient command.\n"); + @smb = <SMB>; + close SMB; + + if ($DEBUG) { # if -d flag print results of nmblookup and smbclient + print "===============================================================\n"; + print @nmblookup; + print @smb; + } + +# look for the OS= string + + @info = grep(/OS=/,@smb); + $_ = @info[0]; + if ($_) { # we found response + s/Domain=|OS=|Server=|\n//g; # strip out descriptions to make line shorter + + } else { # no OS= string in response (WIN95 client) + +# for WIN95 clients get workgroup name from nmblookup response + @name = grep(/<00> - <GROUP>/,@nmblookup); + $_ = @name[0]; + if ($_) { +# Same as before for space and characters + /(.{1,15})\s+<00>\s+/; + $_ = "[$1]"; + } else { + $_ = "Unknown Workgroup"; + } + } + +# see if machine registered a local master browser name + if (grep(/<1d>/,@nmblookup)) { + $master = '+'; # indicate local master browser + if (grep(/<1b>/,@nmblookup)) { # how about domain master browser? + $master = '*'; # indicate domain master browser + } + } else { + $master = ' '; # not a browse master + } + +# line up info in 3 columns + + print "$ip".' 'x(16-length($ip))."$name".' 'x(14-length($name))."$master"."$_\n"; + + } else { # no netbios name found +# try getting the host name + ($name, $aliases, $type, $length, @addresses) = + gethostbyaddr(pack('C4',split('\.',$ip)),2); + if (! $name) { # could not get name + $name = "unknown nis name"; + } + if ($DEBUG) { # if -d flag print results of nmblookup + print "===============================================================\n"; + print @nmblookup; + } + print "$ip".' 'x(16-length($ip))."$name\n"; + } +} + diff --git a/source3/script/findstatic.pl b/source3/script/findstatic.pl new file mode 100755 index 0000000000..43a4916435 --- /dev/null +++ b/source3/script/findstatic.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl -w +# find a list of fns and variables in the code that could be static +# usually called with something like this: +# findstatic.pl `find . -name "*.o"` +# Andrew Tridgell <tridge@samba.org> + +use strict; + +# use nm to find the symbols +my($saved_delim) = $/; +undef $/; +my($syms) = `nm -o @ARGV`; +$/ = $saved_delim; + +my(@lines) = split(/\n/s, $syms); + +my(%def); +my(%undef); +my(%stype); + +my(%typemap) = ( + "T" => "function", + "C" => "uninitialised variable", + "D" => "initialised variable" + ); + + +# parse the symbols into defined and undefined +for (my($i)=0; $i <= $#{@lines}; $i++) { + my($line) = $lines[$i]; + if ($line =~ /(.*):[a-f0-9]* ([TCD]) (.*)/) { + my($fname) = $1; + my($symbol) = $3; + push(@{$def{$fname}}, $symbol); + $stype{$symbol} = $2; + } + if ($line =~ /(.*):\s* U (.*)/) { + my($fname) = $1; + my($symbol) = $2; + push(@{$undef{$fname}}, $symbol); + } +} + +# look for defined symbols that are never referenced outside the place they +# are defined +foreach my $f (keys %def) { + print "Checking $f\n"; + my($found_one) = 0; + foreach my $s (@{$def{$f}}) { + my($found) = 0; + foreach my $f2 (keys %undef) { + if ($f2 ne $f) { + foreach my $s2 (@{$undef{$f2}}) { + if ($s2 eq $s) { + $found = 1; + $found_one = 1; + } + } + } + } + if ($found == 0) { + my($t) = $typemap{$stype{$s}}; + print " '$s' is unique to $f ($t)\n"; + } + } + if ($found_one == 0) { + print " all symbols in '$f' are unused (main program?)\n"; + } +} + diff --git a/source3/tdb/tdbutil.h b/source3/tdb/tdbutil.h new file mode 100644 index 0000000000..01473446a1 --- /dev/null +++ b/source3/tdb/tdbutil.h @@ -0,0 +1,37 @@ +/* + Unix SMB/CIFS implementation. + tdb utility functions + 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. +*/ + +#ifndef __TDBUTIL_H__ +#define __TDBUTIL_H__ + + +/* single node of a list returned by tdb_search_keys */ +typedef struct keys_node +{ + struct keys_node *prev, *next; + TDB_DATA node_key; +} TDB_LIST_NODE; + + +TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*); +void tdb_search_list_free(TDB_LIST_NODE*); + + +#endif /* __TDBUTIL_H__ */ diff --git a/source3/utils/.cvsignore b/source3/utils/.cvsignore new file mode 100644 index 0000000000..6b8749f64e --- /dev/null +++ b/source3/utils/.cvsignore @@ -0,0 +1 @@ +net_proto.h
\ No newline at end of file |