From ae795a09796b35c464c2cc89c53776e63e608686 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Nov 2008 11:02:20 +1100 Subject: we need to remove the pidl Makefile on "make clean" to handle upgrades to perl versions --- pidl/config.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pidl/config.mk b/pidl/config.mk index 45582f5d56..d7a84e3fcc 100644 --- a/pidl/config.mk +++ b/pidl/config.mk @@ -28,4 +28,7 @@ $(pidldir)/lib/Parse/Pidl/Expr.pm: $(pidldir)/idl.yp testcov-html:: pidl-testcov +pidl-clean: + /bin/rm -f $(pidldir)/Makefile +clean:: pidl-clean -- cgit From 41a1c882d4adec957a1ed180b53fd6874d9524f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Nov 2008 11:13:37 +1100 Subject: don't give errors when an empty modules list is given to ldb --- source4/lib/ldb/common/ldb_modules.c | 11 +++++++++-- source4/lib/ldb/include/ldb_private.h | 3 --- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 2b453bb0c3..ab0f4c51cc 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -40,6 +40,9 @@ #define LDB_MODULE_PREFIX "modules:" #define LDB_MODULE_PREFIX_LEN 8 +static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name, + const char *symbol); + void ldb_set_modules_dir(struct ldb_context *ldb, const char *path) { talloc_free(ldb->modules_dir); @@ -291,8 +294,8 @@ int ldb_register_module(const struct ldb_module_ops *ops) return 0; } -void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name, - const char *symbol) +static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name, + const char *symbol) { char *path; void *handle; @@ -334,6 +337,10 @@ int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, str for (i = 0; module_list[i] != NULL; i++) { struct ldb_module *current; const struct ldb_module_ops *ops; + + if (strcmp(module_list[i], "") == 0) { + continue; + } ops = ldb_find_module_ops(module_list[i]); if (ops == NULL) { diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 8f7e010bee..90c4980017 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -259,9 +259,6 @@ const char *ldb_default_modules_dir(void); int ldb_register_backend(const char *url_prefix, ldb_connect_fn); -void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name, - const char *symbol); - struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb); int ldb_module_send_entry(struct ldb_request *req, -- cgit From 30eff4f31b497ac94d8ee02ee2ec24bc8865ce0d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Nov 2008 14:02:40 +1100 Subject: fixed options argument to ldb connect in python The options argument to ldb connect() needs to be marked for the same special handling as attrs in search --- source4/lib/ldb/ldb.i | 4 +++- source4/lib/ldb/ldb_wrap.c | 24 +++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i index 6013462225..35d443e809 100644 --- a/source4/lib/ldb/ldb.i +++ b/source4/lib/ldb/ldb.i @@ -190,6 +190,7 @@ PyObject *ldb_val_to_py_object(struct ldb_context *ldb_ctx, } %apply const char * const *NULL_STR_LIST { const char * const *attrs } +%apply const char * const *NULL_STR_LIST { const char * const *options } %apply const char * const *NULL_STR_LIST { const char * const *control_strings } #endif @@ -712,9 +713,10 @@ typedef struct ldb_context { %feature("docstring") connect "S.connect(url,flags=0,options=None) -> None\n" \ "Connect to a LDB URL."; ldb_error connect(const char *url, unsigned int flags = 0, - const char *options[] = NULL); + const char *const *options = NULL); ~ldb() { talloc_free($self); } + ldb_error search_ex(TALLOC_CTX *mem_ctx, ldb_dn *base = NULL, enum ldb_scope scope = LDB_SCOPE_DEFAULT, diff --git a/source4/lib/ldb/ldb_wrap.c b/source4/lib/ldb/ldb_wrap.c index bc9266a306..194b562c30 100644 --- a/source4/lib/ldb/ldb_wrap.c +++ b/source4/lib/ldb/ldb_wrap.c @@ -4823,7 +4823,7 @@ SWIGINTERN PyObject *_wrap_Ldb_connect(PyObject *SWIGUNUSEDPARM(self), PyObject ldb *arg1 = (ldb *) 0 ; char *arg2 = (char *) 0 ; unsigned int arg3 = (unsigned int) 0 ; - char **arg4 = (char **) (char **)NULL ; + char **arg4 = (char **) NULL ; void *argp1 = 0 ; int res1 = 0 ; int res2 ; @@ -4831,8 +4831,6 @@ SWIGINTERN PyObject *_wrap_Ldb_connect(PyObject *SWIGUNUSEDPARM(self), PyObject int alloc2 = 0 ; unsigned int val3 ; int ecode3 = 0 ; - void *argp4 = 0 ; - int res4 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; @@ -4861,25 +4859,33 @@ SWIGINTERN PyObject *_wrap_Ldb_connect(PyObject *SWIGUNUSEDPARM(self), PyObject arg3 = (unsigned int)(val3); } if (obj3) { - res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_p_char, 0 | 0 ); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Ldb_connect" "', argument " "4"" of type '" "char const *[]""'"); - } - arg4 = (char **)(argp4); + if (obj3 == Py_None) { + arg4 = NULL; + } else if (PySequence_Check(obj3)) { + int i; + arg4 = talloc_array(NULL, char *, PySequence_Size(obj3)+1); + for(i = 0; i < PySequence_Size(obj3); i++) + arg4[i] = PyString_AsString(PySequence_GetItem(obj3, i)); + arg4[i] = NULL; + } else { + SWIG_exception(SWIG_TypeError, "expected sequence"); + } } if (arg1 == NULL) SWIG_exception(SWIG_ValueError, "ldb context must be non-NULL"); - result = ldb_connect(arg1,(char const *)arg2,arg3,(char const *(*))arg4); + result = ldb_connect(arg1,(char const *)arg2,arg3,(char const *const *)arg4); if (result != 0) { PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_errstring(arg1))); SWIG_fail; } resultobj = Py_None; if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + talloc_free(arg4); return resultobj; fail: if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + talloc_free(arg4); return NULL; } -- cgit From 9057c2522adf8d17a07fd3c747d7fed06a523af6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 16 Dec 2008 11:25:29 +1100 Subject: A more-commented version of rpc_server crash fix, matching closer the previous behaviour for the 'bad bind' case. (It is only close, not matching - Windows 2008 sends a different, non-zero, assoc_group_id each time) Andrew Bartlett --- source4/rpc_server/dcerpc_server.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 5f055ae342..d27a8b90de 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -648,7 +648,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags; pkt.u.bind_ack.max_xmit_frag = 0x2000; pkt.u.bind_ack.max_recv_frag = 0x2000; - pkt.u.bind_ack.assoc_group_id = iface?call->context->assoc_group_id:0; + + /* + make it possible for iface->bind() to specify the assoc_group_id + This helps the openchange mapiproxy plugin to work correctly. + + metze + */ + if (call->context) { + pkt.u.bind_ack.assoc_group_id = call->context->assoc_group_id; + } else { + /* we better pick something - this chosen so as to send a non zero assoc_group_id (matching windows), it also matches samba3 */ + pkt.u.bind_ack.assoc_group_id = SAMBA_ASSOC_GROUP; + } + if (iface) { /* FIXME: Use pipe name as specified by endpoint instead of interface name */ pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", iface->name); -- cgit From 2e4247782bd5812bc8e7ea24194c8436748bb2fa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2008 14:36:56 +1100 Subject: make tdbbackup use transactions tdbbackup was originally written before we had transactions, and it attempted to use its own fsync() calls to make it safe. Now that we have transactions we can do it in a much safer (and faster!) fashion --- lib/tdb/tools/tdbbackup.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/tdb/tools/tdbbackup.c b/lib/tdb/tools/tdbbackup.c index 6f3ca48314..83c0e16399 100644 --- a/lib/tdb/tools/tdbbackup.c +++ b/lib/tdb/tools/tdbbackup.c @@ -126,9 +126,17 @@ static int backup_tdb(const char *old_name, const char *new_name, int hash_size) return 1; } - /* lock the old tdb */ - if (tdb_lockall(tdb) != 0) { - fprintf(stderr,"Failed to lock %s\n", old_name); + if (tdb_transaction_start(tdb) != 0) { + printf("Failed to start transaction on old tdb\n"); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + if (tdb_transaction_start(tdb_new) != 0) { + printf("Failed to start transaction on new tdb\n"); tdb_close(tdb); tdb_close(tdb_new); unlink(tmp_name); @@ -152,6 +160,14 @@ static int backup_tdb(const char *old_name, const char *new_name, int hash_size) /* close the old tdb */ tdb_close(tdb); + if (tdb_transaction_commit(tdb_new) != 0) { + fprintf(stderr, "Failed to commit new tdb\n"); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + /* close the new tdb and re-open read-only */ tdb_close(tdb_new); tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0); @@ -173,9 +189,6 @@ static int backup_tdb(const char *old_name, const char *new_name, int hash_size) return 1; } - /* make sure the new tdb has reached stable storage */ - fsync(tdb_fd(tdb_new)); - /* close the new tdb and rename it to .bak */ tdb_close(tdb_new); if (rename(tmp_name, new_name) != 0) { -- cgit From 936d76802f98d04d9743b2ca8eeeaadd4362db51 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2008 14:38:17 +1100 Subject: imported the tdb_repack() code from CTDB The tdb_repack() function repacks a TDB so that it has a single freelist entry. The file doesn't shrink, but it does remove all freelist fragmentation. This code originated in the CTDB vacuuming code, but will now be used in ldb to cope with fragmentation from re-indexing --- lib/tdb/common/tdb.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/tdb/include/tdb.h | 5 ++- 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c index c7cec297f6..8c61ec1a89 100644 --- a/lib/tdb/common/tdb.c +++ b/lib/tdb/common/tdb.c @@ -800,3 +800,92 @@ failed: tdb_unlockall(tdb); return -1; } + +struct traverse_state { + bool error; + struct tdb_context *dest_db; +}; + +/* + traverse function for repacking + */ +static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private) +{ + struct traverse_state *state = (struct traverse_state *)private; + if (tdb_store(state->dest_db, key, data, TDB_INSERT) != 0) { + state->error = true; + return -1; + } + return 0; +} + +/* + repack a tdb + */ +int tdb_repack(struct tdb_context *tdb) +{ + struct tdb_context *tmp_db; + struct traverse_state state; + + if (tdb_transaction_start(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to start transaction\n")); + return -1; + } + + tmp_db = tdb_open("tmpdb", tdb_hash_size(tdb), TDB_INTERNAL, O_RDWR|O_CREAT, 0); + if (tmp_db == NULL) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to create tmp_db\n")); + tdb_transaction_cancel(tdb); + return -1; + } + + state.error = false; + state.dest_db = tmp_db; + + if (tdb_traverse_read(tdb, repack_traverse, &state) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying out\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (state.error) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during traversal\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (tdb_wipe_all(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to wipe database\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + state.error = false; + state.dest_db = tdb; + + if (tdb_traverse_read(tmp_db, repack_traverse, &state) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to traverse copying back\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + if (state.error) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Error during second traversal\n")); + tdb_transaction_cancel(tdb); + tdb_close(tmp_db); + return -1; + } + + tdb_close(tmp_db); + + if (tdb_transaction_commit(tdb) != 0) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, __location__ " Failed to commit\n")); + return -1; + } + + return 0; +} diff --git a/lib/tdb/include/tdb.h b/lib/tdb/include/tdb.h index c41c9941f0..94b5e366b9 100644 --- a/lib/tdb/include/tdb.h +++ b/lib/tdb/include/tdb.h @@ -152,11 +152,14 @@ int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key); void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *sigptr); +/* wipe and repack */ +int tdb_wipe_all(struct tdb_context *tdb); +int tdb_repack(struct tdb_context *tdb); + /* Debug functions. Not used in production. */ void tdb_dump_all(struct tdb_context *tdb); int tdb_printfreelist(struct tdb_context *tdb); int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries); -int tdb_wipe_all(struct tdb_context *tdb); int tdb_freelist_size(struct tdb_context *tdb); extern TDB_DATA tdb_null; -- cgit From f320e3a659d2ef701e3770071375ca9781d98325 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2008 14:39:42 +1100 Subject: use transactions in ldbadd, ldbmodify and ldbedit The command line tools ldbadd, ldbmodify and ldbedit should operate within a transaction to make them more efficient. The ldbadd tool in particular is much faster when adding a large number of records if all the adds happen within a transaction. Previously there was a transaction per record. --- source4/lib/ldb/tools/ldbadd.c | 10 ++++++++++ source4/lib/ldb/tools/ldbedit.c | 10 ++++++++++ source4/lib/ldb/tools/ldbmodify.c | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c index 15376e7342..3749aec629 100644 --- a/source4/lib/ldb/tools/ldbadd.c +++ b/source4/lib/ldb/tools/ldbadd.c @@ -92,6 +92,11 @@ int main(int argc, const char **argv) options = ldb_cmdline_process(ldb, argc, argv, usage); + if (ldb_transaction_start(ldb) != 0) { + printf("Failed to start transaction\n"); + exit(1); + } + if (options->argc == 0) { ret = process_file(ldb, stdin, &count); } else { @@ -108,6 +113,11 @@ int main(int argc, const char **argv) } } + if (count != 0 && ldb_transaction_commit(ldb) != 0) { + printf("Failed to commit transaction\n"); + exit(1); + } + talloc_free(ldb); printf("Added %d records with %d failures\n", count, failures); diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c index b2a040cd09..b18aea1b10 100644 --- a/source4/lib/ldb/tools/ldbedit.c +++ b/source4/lib/ldb/tools/ldbedit.c @@ -112,6 +112,11 @@ static int merge_edits(struct ldb_context *ldb, int ret = 0; int adds=0, modifies=0, deletes=0; + if (ldb_transaction_start(ldb) != 0) { + fprintf(stderr, "Failed to start transaction\n"); + return -1; + } + /* do the adds and modifies */ for (i=0;idn); @@ -150,6 +155,11 @@ static int merge_edits(struct ldb_context *ldb, } } + if (ldb_transaction_commit(ldb) != 0) { + fprintf(stderr, "Failed to commit transaction\n"); + return -1; + } + printf("# %d adds %d modifies %d deletes\n", adds, modifies, deletes); return ret; diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c index 6e355a10cf..8b6309e016 100644 --- a/source4/lib/ldb/tools/ldbmodify.c +++ b/source4/lib/ldb/tools/ldbmodify.c @@ -91,6 +91,11 @@ int main(int argc, const char **argv) ldb = ldb_init(NULL, NULL); + if (ldb_transaction_start(ldb) != 0) { + printf("Failed to start transaction\n"); + exit(1); + } + options = ldb_cmdline_process(ldb, argc, argv, usage); if (options->argc == 0) { @@ -108,6 +113,11 @@ int main(int argc, const char **argv) } } + if (count != 0 && ldb_transaction_commit(ldb) != 0) { + printf("Failed to commit transaction\n"); + exit(1); + } + talloc_free(ldb); printf("Modified %d records with %d failures\n", count, failures); -- cgit From 4380a374c1dec46ad77939604e548f0c79d9e2ec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 16 Dec 2008 14:41:21 +1100 Subject: repack the ldb after re-indexing re-indexing in ldb is triggered on any modification to the @ATTRIBUTES or @INDEXLIST records. This happens to produce a worst-case fragmentation of the database, as all @INDEX records are deleted then re-created. By repacking after re-indexing we ensure that the database ends up without extreme fragmentation. --- source4/lib/ldb/ldb_tdb/ldb_index.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 65711d9f4b..eedbda4170 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -1250,5 +1250,9 @@ int ltdb_reindex(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } + if (tdb_repack(ltdb->tdb) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + return LDB_SUCCESS; } -- cgit From 8e1db7eab17ea0dcb052bc330ab31636906a59fe Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Mon, 15 Dec 2008 22:34:07 -0800 Subject: s3: Fix a few build warnings --- source3/modules/getdate.c | 1397 ++++++++++++++++++++++++++++----------------- source3/modules/getdate.y | 18 +- 2 files changed, 891 insertions(+), 524 deletions(-) diff --git a/source3/modules/getdate.c b/source3/modules/getdate.c index 149a3e1ab9..a27b75f7f1 100644 --- a/source3/modules/getdate.c +++ b/source3/modules/getdate.c @@ -1,7 +1,9 @@ -/* A Bison parser, made by GNU Bison 1.875a. */ +/* A Bison parser, made by GNU Bison 2.3. */ -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. 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 @@ -14,15 +16,25 @@ 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, see . */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* Written by Richard Stallman by simplifying the original so called - ``semantic'' parser. */ + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local @@ -34,6 +46,9 @@ /* Identify Bison output. */ #define YYBISON 1 +/* Bison version. */ +#define YYBISON_VERSION "2.3" + /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -69,6 +84,7 @@ tUNUMBER = 273 }; #endif +/* Tokens. */ #define tAGO 258 #define tDST 259 #define tDAY 260 @@ -250,9 +266,6 @@ typedef struct #define YYLEX_PARAM parm #define YYPARSE_PARAM parm -static int yyerror (); -static int yylex (); - /* Enabling traces. */ @@ -268,14 +281,21 @@ static int yylex (); # define YYERROR_VERBOSE 0 #endif -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 172 "getdate.y" -typedef union YYSTYPE { +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 169 "getdate.y" +{ int intval; textint textintval; -} YYSTYPE; -/* Line 191 of yacc.c. */ -#line 281 "getdate.c" +} +/* Line 187 of yacc.c. */ +#line 298 "getdate.c" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 @@ -284,51 +304,179 @@ typedef union YYSTYPE { /* Copy the second part of user declarations. */ +#line 174 "getdate.y" -/* Line 214 of yacc.c. */ -#line 293 "getdate.c" +static int yyerror(const char *); +static int yylex(YYSTYPE *, parser_control *); -#if ! defined (yyoverflow) || YYERROR_VERBOSE -/* The parser invokes alloca or malloc; define the necessary symbols. */ -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca +/* Line 216 of yacc.c. */ +#line 317 "getdate.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t # else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca # else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif # else -# if defined (__STDC__) || defined (__cplusplus) +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif # endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free # endif -#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (YYSTYPE_IS_TRIVIAL))) +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - short yyss; + yytype_int16 yyss; YYSTYPE yyvs; }; @@ -338,24 +486,24 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY -# if 1 < __GNUC__ +# if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ - register YYSIZE_T yyi; \ + YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ - while (0) + while (YYID (0)) # endif # endif @@ -373,39 +521,33 @@ union yyalloc yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ - while (0) + while (YYID (0)) #endif -#if defined (__STDC__) || defined (__cplusplus) - typedef signed char yysigned_char; -#else - typedef short yysigned_char; -#endif - -/* YYFINAL -- State number of the termination state. */ +/* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 52 -/* YYNTOKENS -- Number of terminals. */ +/* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 22 -/* YYNNTS -- Number of nonterminals. */ +/* YYNNTS -- Number of nonterminals. */ #define YYNNTS 12 -/* YYNRULES -- Number of rules. */ +/* YYNRULES -- Number of rules. */ #define YYNRULES 54 -/* YYNRULES -- Number of states. */ +/* YYNRULES -- Number of states. */ #define YYNSTATES 64 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 273 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const unsigned char yytranslate[] = +static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -440,7 +582,7 @@ static const unsigned char yytranslate[] = #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ -static const unsigned char yyprhs[] = +static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 7, 9, 11, 13, 15, 17, 19, 21, 24, 29, 34, 41, 48, 50, 53, 55, @@ -450,8 +592,8 @@ static const unsigned char yyprhs[] = 149, 152, 154, 156, 157 }; -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yysigned_char yyrhs[] = +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = { 23, 0, -1, -1, 23, 24, -1, 25, -1, 26, -1, 27, -1, 29, -1, 28, -1, 30, -1, 32, @@ -472,27 +614,27 @@ static const yysigned_char yyrhs[] = }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned short yyrline[] = +static const yytype_uint16 yyrline[] = { - 0, 188, 188, 190, 194, 196, 198, 200, 202, 204, - 206, 210, 217, 224, 232, 239, 251, 253, 258, 260, - 262, 267, 272, 277, 285, 290, 310, 317, 325, 330, - 336, 341, 350, 359, 363, 365, 367, 369, 371, 373, - 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, - 395, 397, 402, 439, 440 + 0, 192, 192, 194, 198, 200, 202, 204, 206, 208, + 210, 214, 221, 228, 236, 243, 255, 257, 262, 264, + 266, 271, 276, 281, 289, 294, 314, 321, 329, 334, + 340, 345, 354, 363, 367, 369, 371, 373, 375, 377, + 379, 381, 383, 385, 387, 389, 391, 393, 395, 397, + 399, 401, 406, 443, 444 }; #endif -#if YYDEBUG || YYERROR_VERBOSE -/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { - "$end", "error", "$undefined", "tAGO", "tDST", "tDAY", "tDAY_UNIT", - "tDAYZONE", "tHOUR_UNIT", "tLOCAL_ZONE", "tMERIDIAN", "tMINUTE_UNIT", - "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tYEAR_UNIT", "tZONE", "tSNUMBER", - "tUNUMBER", "':'", "','", "'/'", "$accept", "spec", "item", "time", - "local_zone", "zone", "day", "date", "rel", "relunit", "number", + "$end", "error", "$undefined", "tAGO", "tDST", "tDAY", "tDAY_UNIT", + "tDAYZONE", "tHOUR_UNIT", "tLOCAL_ZONE", "tMERIDIAN", "tMINUTE_UNIT", + "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tYEAR_UNIT", "tZONE", "tSNUMBER", + "tUNUMBER", "':'", "','", "'/'", "$accept", "spec", "item", "time", + "local_zone", "zone", "day", "date", "rel", "relunit", "number", "o_merid", 0 }; #endif @@ -500,7 +642,7 @@ static const char *const yytname[] = # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ -static const unsigned short yytoknum[] = +static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 58, @@ -509,7 +651,7 @@ static const unsigned short yytoknum[] = # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const unsigned char yyr1[] = +static const yytype_uint8 yyr1[] = { 0, 22, 23, 23, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 26, 26, 27, 27, @@ -520,7 +662,7 @@ static const unsigned char yyr1[] = }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const unsigned char yyr2[] = +static const yytype_uint8 yyr2[] = { 0, 2, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4, 6, 6, 1, 2, 1, 1, @@ -533,7 +675,7 @@ static const unsigned char yyr2[] = /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ -static const unsigned char yydefact[] = +static const yytype_uint8 yydefact[] = { 2, 0, 1, 21, 42, 19, 45, 16, 48, 0, 39, 51, 36, 18, 0, 52, 3, 4, 5, 6, @@ -544,8 +686,8 @@ static const unsigned char yydefact[] = 53, 25, 15, 14 }; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yysigned_char yydefgoto[] = +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { -1, 1, 16, 17, 18, 19, 20, 21, 22, 23, 24, 58 @@ -554,7 +696,7 @@ static const yysigned_char yydefgoto[] = /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -17 -static const yysigned_char yypact[] = +static const yytype_int8 yypact[] = { -17, 0, -17, 1, -17, -17, -17, 19, -17, -14, -17, -17, -17, 32, 26, 14, -17, -17, -17, -17, @@ -566,7 +708,7 @@ static const yysigned_char yypact[] = }; /* YYPGOTO[NTERM-NUM]. */ -static const yysigned_char yypgoto[] = +static const yytype_int8 yypgoto[] = { -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, -10 @@ -577,7 +719,7 @@ static const yysigned_char yypgoto[] = number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 -static const unsigned char yytable[] = +static const yytype_uint8 yytable[] = { 2, 49, 50, 55, 27, 3, 4, 5, 6, 7, 62, 8, 9, 10, 11, 12, 13, 14, 15, 35, @@ -587,7 +729,7 @@ static const unsigned char yytable[] = 63, 60, 61 }; -static const unsigned char yycheck[] = +static const yytype_uint8 yycheck[] = { 0, 17, 18, 10, 18, 5, 6, 7, 8, 9, 17, 11, 12, 13, 14, 15, 16, 17, 18, 5, @@ -599,7 +741,7 @@ static const unsigned char yycheck[] = /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ -static const unsigned char yystos[] = +static const yytype_uint8 yystos[] = { 0, 23, 0, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 24, 25, 26, 27, @@ -610,22 +752,6 @@ static const unsigned char yystos[] = 18, 18, 17, 33 }; -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -#endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int -#endif - #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) @@ -633,7 +759,7 @@ static const unsigned char yystos[] = #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 +#define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily @@ -651,30 +777,63 @@ do \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ + YYPOPSTACK (1); \ goto yybackup; \ } \ else \ - { \ - yyerror ("syntax error: cannot back up");\ + { \ + yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ -while (0) +while (YYID (0)) + #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). */ +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.first_line = Rhs[1].first_line; \ - Current.first_column = Rhs[1].first_column; \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif #endif + /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM @@ -695,42 +854,96 @@ while (0) do { \ if (yydebug) \ YYFPRINTF Args; \ -} while (0) +} while (YYID (0)) -# define YYDSYMPRINT(Args) \ -do { \ - if (yydebug) \ - yysymprint Args; \ -} while (0) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) -# define YYDSYMPRINTF(Title, Token, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ - Token, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (cinluded). | +| TOP (included). | `------------------------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (short *bottom, short *top) +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) - short *bottom; - short *top; + yytype_int16 *bottom; + yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); - for (/* Nothing. */; bottom <= top; ++bottom) + for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } @@ -739,45 +952,52 @@ yy_stack_print (bottom, top) do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ -} while (0) +} while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (int yyrule) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void -yy_reduce_print (yyrule) +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; int yyrule; #endif { + int yynrhs = yyr2[yyrule]; int yyi; - unsigned int yylineno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", - yyrule - 1, yylineno); - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (Rule); \ -} while (0) + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) -# define YYDSYMPRINT(Args) -# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ @@ -792,13 +1012,9 @@ int yydebug; if the built-in stack extension method is used). Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#if YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif - #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif @@ -808,45 +1024,47 @@ int yydebug; #if YYERROR_VERBOSE # ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) +# if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) -# else +#else +static YYSIZE_T yystrlen (yystr) - const char *yystr; -# endif + const char *yystr; +#endif { - register const char *yys = yystr; - - while (*yys++ != '\0') + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) continue; - - return yys - yystr - 1; + return yylen; } # endif # endif # ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static char * -# if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) -# else +#else +static char * yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif + char *yydest; + const char *yysrc; +#endif { - register char *yyd = yydest; - register const char *yys = yysrc; + char *yyd = yydest; + const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; @@ -856,70 +1074,192 @@ yystpcpy (yydest, yysrc) # endif # endif -#endif /* !YYERROR_VERBOSE */ +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; - + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } -#if YYDEBUG -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ + if (! yyres) + return yystrlen (yystr); -#if defined (__STDC__) || defined (__cplusplus) -static void -yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) -#else -static void -yysymprint (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE *yyvaluep; -#endif + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; + int yyn = yypact[yystate]; - if (yytype < YYNTOKENS) + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else { - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); -# ifdef YYPRINT - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif - } - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } - switch (yytype) - { - default: - break; + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; } - YYFPRINTF (yyoutput, ")"); } +#endif /* YYERROR_VERBOSE */ + -#endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yydestruct (int yytype, YYSTYPE *yyvaluep) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void -yydestruct (yytype, yyvaluep) +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: - break; + break; } } @@ -927,13 +1267,13 @@ yydestruct (yytype, yyvaluep) /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) +#if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); -# else +#else int yyparse (); -# endif +#endif #else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) +#if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); @@ -950,14 +1290,18 @@ int yyparse (); `----------*/ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM) -# else -int yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -# endif +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif #else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else @@ -967,22 +1311,28 @@ yyparse () #endif #endif { - /* The lookahead symbol. */ + /* The look-ahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ +/* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; - register int yystate; - register int yyn; + int yystate; + int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ + /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif /* Three stacks and their tools: `yyss': related to states, @@ -993,18 +1343,18 @@ int yynerrs; to reallocate them elsewhere. */ /* The state stack. */ - short yyssa[YYINITDEPTH]; - short *yyss = yyssa; - register short *yyssp; + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; - register YYSTYPE *yyvsp; + YYSTYPE *yyvsp; -#define YYPOPSTACK (yyvsp--, yyssp--) +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; @@ -1013,9 +1363,9 @@ int yynerrs; YYSTYPE yyval; - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1039,8 +1389,7 @@ int yynerrs; `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ + have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: @@ -1053,18 +1402,18 @@ int yynerrs; #ifdef yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of + /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; + yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", + yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), @@ -1075,21 +1424,21 @@ int yynerrs; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE - goto yyoverflowlab; + goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyoverflowlab; + goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { - short *yyss1 = yyss; + yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) - goto yyoverflowlab; + goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); @@ -1120,19 +1469,17 @@ int yynerrs; `-----------*/ yybackup: -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ - - /* First try to decide what to do without reference to lookahead token. */ + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; - /* Not known => get a lookahead token if don't already have one. */ + /* Not known => get a look-ahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); @@ -1147,7 +1494,7 @@ yybackup: else { yytoken = YYTRANSLATE (yychar); - YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to @@ -1167,22 +1514,21 @@ yybackup: if (yyn == YYFINAL) YYACCEPT; - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; - - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + yystate = yyn; + *++yyvsp = yylval; + goto yynewstate; @@ -1218,225 +1564,225 @@ yyreduce: switch (yyn) { case 4: -#line 195 "getdate.y" - { PC.times_seen++; } +#line 199 "getdate.y" + { PC.times_seen++; ;} break; case 5: -#line 197 "getdate.y" - { PC.local_zones_seen++; } +#line 201 "getdate.y" + { PC.local_zones_seen++; ;} break; case 6: -#line 199 "getdate.y" - { PC.zones_seen++; } +#line 203 "getdate.y" + { PC.zones_seen++; ;} break; case 7: -#line 201 "getdate.y" - { PC.dates_seen++; } +#line 205 "getdate.y" + { PC.dates_seen++; ;} break; case 8: -#line 203 "getdate.y" - { PC.days_seen++; } +#line 207 "getdate.y" + { PC.days_seen++; ;} break; case 9: -#line 205 "getdate.y" - { PC.rels_seen++; } +#line 209 "getdate.y" + { PC.rels_seen++; ;} break; case 11: -#line 211 "getdate.y" +#line 215 "getdate.y" { - PC.hour = yyvsp[-1].textintval.value; + PC.hour = (yyvsp[(1) - (2)].textintval).value; PC.minutes = 0; PC.seconds = 0; - PC.meridian = yyvsp[0].intval; - } + PC.meridian = (yyvsp[(2) - (2)].intval); + ;} break; case 12: -#line 218 "getdate.y" +#line 222 "getdate.y" { - PC.hour = yyvsp[-3].textintval.value; - PC.minutes = yyvsp[-1].textintval.value; + PC.hour = (yyvsp[(1) - (4)].textintval).value; + PC.minutes = (yyvsp[(3) - (4)].textintval).value; PC.seconds = 0; - PC.meridian = yyvsp[0].intval; - } + PC.meridian = (yyvsp[(4) - (4)].intval); + ;} break; case 13: -#line 225 "getdate.y" +#line 229 "getdate.y" { - PC.hour = yyvsp[-3].textintval.value; - PC.minutes = yyvsp[-1].textintval.value; + PC.hour = (yyvsp[(1) - (4)].textintval).value; + PC.minutes = (yyvsp[(3) - (4)].textintval).value; PC.meridian = MER24; PC.zones_seen++; - PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60; - } + PC.time_zone = (yyvsp[(4) - (4)].textintval).value % 100 + ((yyvsp[(4) - (4)].textintval).value / 100) * 60; + ;} break; case 14: -#line 233 "getdate.y" +#line 237 "getdate.y" { - PC.hour = yyvsp[-5].textintval.value; - PC.minutes = yyvsp[-3].textintval.value; - PC.seconds = yyvsp[-1].textintval.value; - PC.meridian = yyvsp[0].intval; - } + PC.hour = (yyvsp[(1) - (6)].textintval).value; + PC.minutes = (yyvsp[(3) - (6)].textintval).value; + PC.seconds = (yyvsp[(5) - (6)].textintval).value; + PC.meridian = (yyvsp[(6) - (6)].intval); + ;} break; case 15: -#line 240 "getdate.y" +#line 244 "getdate.y" { - PC.hour = yyvsp[-5].textintval.value; - PC.minutes = yyvsp[-3].textintval.value; - PC.seconds = yyvsp[-1].textintval.value; + PC.hour = (yyvsp[(1) - (6)].textintval).value; + PC.minutes = (yyvsp[(3) - (6)].textintval).value; + PC.seconds = (yyvsp[(5) - (6)].textintval).value; PC.meridian = MER24; PC.zones_seen++; - PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60; - } + PC.time_zone = (yyvsp[(6) - (6)].textintval).value % 100 + ((yyvsp[(6) - (6)].textintval).value / 100) * 60; + ;} break; case 16: -#line 252 "getdate.y" - { PC.local_isdst = yyvsp[0].intval; } +#line 256 "getdate.y" + { PC.local_isdst = (yyvsp[(1) - (1)].intval); ;} break; case 17: -#line 254 "getdate.y" - { PC.local_isdst = yyvsp[-1].intval < 0 ? 1 : yyvsp[-1].intval + 1; } +#line 258 "getdate.y" + { PC.local_isdst = (yyvsp[(1) - (2)].intval) < 0 ? 1 : (yyvsp[(1) - (2)].intval) + 1; ;} break; case 18: -#line 259 "getdate.y" - { PC.time_zone = yyvsp[0].intval; } +#line 263 "getdate.y" + { PC.time_zone = (yyvsp[(1) - (1)].intval); ;} break; case 19: -#line 261 "getdate.y" - { PC.time_zone = yyvsp[0].intval + 60; } +#line 265 "getdate.y" + { PC.time_zone = (yyvsp[(1) - (1)].intval) + 60; ;} break; case 20: -#line 263 "getdate.y" - { PC.time_zone = yyvsp[-1].intval + 60; } +#line 267 "getdate.y" + { PC.time_zone = (yyvsp[(1) - (2)].intval) + 60; ;} break; case 21: -#line 268 "getdate.y" +#line 272 "getdate.y" { PC.day_ordinal = 1; - PC.day_number = yyvsp[0].intval; - } + PC.day_number = (yyvsp[(1) - (1)].intval); + ;} break; case 22: -#line 273 "getdate.y" +#line 277 "getdate.y" { PC.day_ordinal = 1; - PC.day_number = yyvsp[-1].intval; - } + PC.day_number = (yyvsp[(1) - (2)].intval); + ;} break; case 23: -#line 278 "getdate.y" +#line 282 "getdate.y" { - PC.day_ordinal = yyvsp[-1].textintval.value; - PC.day_number = yyvsp[0].intval; - } + PC.day_ordinal = (yyvsp[(1) - (2)].textintval).value; + PC.day_number = (yyvsp[(2) - (2)].intval); + ;} break; case 24: -#line 286 "getdate.y" +#line 290 "getdate.y" { - PC.month = yyvsp[-2].textintval.value; - PC.day = yyvsp[0].textintval.value; - } + PC.month = (yyvsp[(1) - (3)].textintval).value; + PC.day = (yyvsp[(3) - (3)].textintval).value; + ;} break; case 25: -#line 291 "getdate.y" +#line 295 "getdate.y" { /* Interpret as YYYY/MM/DD if the first value has 4 or more digits, otherwise as MM/DD/YY. The goal in recognizing YYYY/MM/DD is solely to support legacy machine-generated dates like those in an RCS log listing. If you want portability, use the ISO 8601 format. */ - if (4 <= yyvsp[-4].textintval.digits) + if (4 <= (yyvsp[(1) - (5)].textintval).digits) { - PC.year = yyvsp[-4].textintval; - PC.month = yyvsp[-2].textintval.value; - PC.day = yyvsp[0].textintval.value; + PC.year = (yyvsp[(1) - (5)].textintval); + PC.month = (yyvsp[(3) - (5)].textintval).value; + PC.day = (yyvsp[(5) - (5)].textintval).value; } else { - PC.month = yyvsp[-4].textintval.value; - PC.day = yyvsp[-2].textintval.value; - PC.year = yyvsp[0].textintval; + PC.month = (yyvsp[(1) - (5)].textintval).value; + PC.day = (yyvsp[(3) - (5)].textintval).value; + PC.year = (yyvsp[(5) - (5)].textintval); } - } + ;} break; case 26: -#line 311 "getdate.y" +#line 315 "getdate.y" { /* ISO 8601 format. YYYY-MM-DD. */ - PC.year = yyvsp[-2].textintval; - PC.month = -yyvsp[-1].textintval.value; - PC.day = -yyvsp[0].textintval.value; - } + PC.year = (yyvsp[(1) - (3)].textintval); + PC.month = -(yyvsp[(2) - (3)].textintval).value; + PC.day = -(yyvsp[(3) - (3)].textintval).value; + ;} break; case 27: -#line 318 "getdate.y" +#line 322 "getdate.y" { /* e.g. 17-JUN-1992. */ - PC.day = yyvsp[-2].textintval.value; - PC.month = yyvsp[-1].intval; - PC.year.value = -yyvsp[0].textintval.value; - PC.year.digits = yyvsp[0].textintval.digits; - } + PC.day = (yyvsp[(1) - (3)].textintval).value; + PC.month = (yyvsp[(2) - (3)].intval); + PC.year.value = -(yyvsp[(3) - (3)].textintval).value; + PC.year.digits = (yyvsp[(3) - (3)].textintval).digits; + ;} break; case 28: -#line 326 "getdate.y" +#line 330 "getdate.y" { - PC.month = yyvsp[-1].intval; - PC.day = yyvsp[0].textintval.value; - } + PC.month = (yyvsp[(1) - (2)].intval); + PC.day = (yyvsp[(2) - (2)].textintval).value; + ;} break; case 29: -#line 331 "getdate.y" +#line 335 "getdate.y" { - PC.month = yyvsp[-3].intval; - PC.day = yyvsp[-2].textintval.value; - PC.year = yyvsp[0].textintval; - } + PC.month = (yyvsp[(1) - (4)].intval); + PC.day = (yyvsp[(2) - (4)].textintval).value; + PC.year = (yyvsp[(4) - (4)].textintval); + ;} break; case 30: -#line 337 "getdate.y" +#line 341 "getdate.y" { - PC.day = yyvsp[-1].textintval.value; - PC.month = yyvsp[0].intval; - } + PC.day = (yyvsp[(1) - (2)].textintval).value; + PC.month = (yyvsp[(2) - (2)].intval); + ;} break; case 31: -#line 342 "getdate.y" +#line 346 "getdate.y" { - PC.day = yyvsp[-2].textintval.value; - PC.month = yyvsp[-1].intval; - PC.year = yyvsp[0].textintval; - } + PC.day = (yyvsp[(1) - (3)].textintval).value; + PC.month = (yyvsp[(2) - (3)].intval); + PC.year = (yyvsp[(3) - (3)].textintval); + ;} break; case 32: -#line 351 "getdate.y" +#line 355 "getdate.y" { PC.rel_seconds = -PC.rel_seconds; PC.rel_minutes = -PC.rel_minutes; @@ -1444,155 +1790,154 @@ yyreduce: PC.rel_day = -PC.rel_day; PC.rel_month = -PC.rel_month; PC.rel_year = -PC.rel_year; - } + ;} break; case 34: -#line 364 "getdate.y" - { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 368 "getdate.y" + { PC.rel_year += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 35: -#line 366 "getdate.y" - { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 370 "getdate.y" + { PC.rel_year += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 36: -#line 368 "getdate.y" - { PC.rel_year += yyvsp[0].intval; } +#line 372 "getdate.y" + { PC.rel_year += (yyvsp[(1) - (1)].intval); ;} break; case 37: -#line 370 "getdate.y" - { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 374 "getdate.y" + { PC.rel_month += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 38: -#line 372 "getdate.y" - { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 376 "getdate.y" + { PC.rel_month += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 39: -#line 374 "getdate.y" - { PC.rel_month += yyvsp[0].intval; } +#line 378 "getdate.y" + { PC.rel_month += (yyvsp[(1) - (1)].intval); ;} break; case 40: -#line 376 "getdate.y" - { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 380 "getdate.y" + { PC.rel_day += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 41: -#line 378 "getdate.y" - { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 382 "getdate.y" + { PC.rel_day += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 42: -#line 380 "getdate.y" - { PC.rel_day += yyvsp[0].intval; } +#line 384 "getdate.y" + { PC.rel_day += (yyvsp[(1) - (1)].intval); ;} break; case 43: -#line 382 "getdate.y" - { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 386 "getdate.y" + { PC.rel_hour += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 44: -#line 384 "getdate.y" - { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 388 "getdate.y" + { PC.rel_hour += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 45: -#line 386 "getdate.y" - { PC.rel_hour += yyvsp[0].intval; } +#line 390 "getdate.y" + { PC.rel_hour += (yyvsp[(1) - (1)].intval); ;} break; case 46: -#line 388 "getdate.y" - { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 392 "getdate.y" + { PC.rel_minutes += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 47: -#line 390 "getdate.y" - { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 394 "getdate.y" + { PC.rel_minutes += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 48: -#line 392 "getdate.y" - { PC.rel_minutes += yyvsp[0].intval; } +#line 396 "getdate.y" + { PC.rel_minutes += (yyvsp[(1) - (1)].intval); ;} break; case 49: -#line 394 "getdate.y" - { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 398 "getdate.y" + { PC.rel_seconds += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 50: -#line 396 "getdate.y" - { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; } +#line 400 "getdate.y" + { PC.rel_seconds += (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); ;} break; case 51: -#line 398 "getdate.y" - { PC.rel_seconds += yyvsp[0].intval; } +#line 402 "getdate.y" + { PC.rel_seconds += (yyvsp[(1) - (1)].intval); ;} break; case 52: -#line 403 "getdate.y" +#line 407 "getdate.y" { if (PC.dates_seen - && ! PC.rels_seen && (PC.times_seen || 2 < yyvsp[0].textintval.digits)) - PC.year = yyvsp[0].textintval; + && ! PC.rels_seen && (PC.times_seen || 2 < (yyvsp[(1) - (1)].textintval).digits)) + PC.year = (yyvsp[(1) - (1)].textintval); else { - if (4 < yyvsp[0].textintval.digits) + if (4 < (yyvsp[(1) - (1)].textintval).digits) { PC.dates_seen++; - PC.day = yyvsp[0].textintval.value % 100; - PC.month = (yyvsp[0].textintval.value / 100) % 100; - PC.year.value = yyvsp[0].textintval.value / 10000; - PC.year.digits = yyvsp[0].textintval.digits - 4; + PC.day = (yyvsp[(1) - (1)].textintval).value % 100; + PC.month = ((yyvsp[(1) - (1)].textintval).value / 100) % 100; + PC.year.value = (yyvsp[(1) - (1)].textintval).value / 10000; + PC.year.digits = (yyvsp[(1) - (1)].textintval).digits - 4; } else { PC.times_seen++; - if (yyvsp[0].textintval.digits <= 2) + if ((yyvsp[(1) - (1)].textintval).digits <= 2) { - PC.hour = yyvsp[0].textintval.value; + PC.hour = (yyvsp[(1) - (1)].textintval).value; PC.minutes = 0; } else { - PC.hour = yyvsp[0].textintval.value / 100; - PC.minutes = yyvsp[0].textintval.value % 100; + PC.hour = (yyvsp[(1) - (1)].textintval).value / 100; + PC.minutes = (yyvsp[(1) - (1)].textintval).value % 100; } PC.seconds = 0; PC.meridian = MER24; } } - } + ;} break; case 53: -#line 439 "getdate.y" - { yyval.intval = MER24; } +#line 443 "getdate.y" + { (yyval.intval) = MER24; ;} break; case 54: -#line 441 "getdate.y" - { yyval.intval = yyvsp[0].intval; } +#line 445 "getdate.y" + { (yyval.intval) = (yyvsp[(1) - (1)].intval); ;} break; +/* Line 1267 of yacc.c. */ +#line 1935 "getdate.c" + default: break; } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); -/* Line 999 of yacc.c. */ -#line 1593 "getdate.c" - - yyvsp -= yylen; - yyssp -= yylen; - - + YYPOPSTACK (yylen); + yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; @@ -1621,92 +1966,92 @@ yyerrlab: if (!yyerrstatus) { ++yynerrs; -#if YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (YYPACT_NINF < yyn && yyn < YYLAST) - { - YYSIZE_T yysize = 0; - int yytype = YYTRANSLATE (yychar); - char *yymsg; - int yyx, yycount; - - yycount = 0; - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("syntax error, unexpected ") + 1; - yysize += yystrlen (yytname[yytype]); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) - { - char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); - yyp = yystpcpy (yyp, yytname[yytype]); - - if (yycount < 5) - { - yycount = 0; - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); - yyx++) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - const char *yyq = ! yycount ? ", expecting " : " or "; - yyp = yystpcpy (yyp, yyq); - yyp = yystpcpy (yyp, yytname[yyx]); - yycount++; - } - } - yyerror (yymsg); +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); - } - else - yyerror ("syntax error; also virtual memory exhausted"); - } - else -#endif /* YYERROR_VERBOSE */ - yyerror ("syntax error"); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif } if (yyerrstatus == 3) { - /* If just tried and failed to reuse lookahead token after an + /* If just tried and failed to reuse look-ahead token after an error, discard it. */ - /* Return failure if at end of input. */ - if (yychar == YYEOF) - { - /* Pop the error token. */ - YYPOPSTACK; - /* Pop the rest of the stack. */ - while (yyss < yyssp) - { - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[*yyssp], yyvsp); - YYPOPSTACK; - } - YYABORT; - } - - YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); - yydestruct (yytoken, &yylval); - yychar = YYEMPTY; - + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } } - /* Else will try to reuse lookahead token after shifting the error + /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; -/*----------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action. | -`----------------------------------------------------*/ +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ @@ -1728,22 +2073,23 @@ yyerrlab1: if (yyssp == yyss) YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[yystate], yyvsp); - yyvsp--; - yystate = *--yyssp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; - YYDPRINTF ((stderr, "Shifting error token, ")); - *++yyvsp = yylval; + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + yystate = yyn; goto yynewstate; @@ -1763,25 +2109,43 @@ yyabortlab: goto yyreturn; #ifndef yyoverflow -/*----------------------------------------------. -| yyoverflowlab -- parser overflow comes here. | -`----------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif - return yyresult; +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); } -#line 444 "getdate.y" +#line 448 "getdate.y" /* Include this file down here because bison inserts code above which @@ -1790,13 +2154,13 @@ yyreturn: #include "modules/getdate.h" #ifndef gmtime -struct tm *gmtime (); +struct tm *gmtime (const time_t *); #endif #ifndef localtime -struct tm *localtime (); +struct tm *localtime (const time_t *); #endif #ifndef mktime -time_t mktime (); +time_t mktime (struct tm *); #endif static table const meridian_table[] = @@ -2204,7 +2568,7 @@ yylex (YYSTYPE *lvalp, parser_control *pc) /* Do nothing if the parser reports an error. */ static int -yyerror (char *s ATTRIBUTE_UNUSED) +yyerror (const char *s ATTRIBUTE_UNUSED) { return 0; } @@ -2455,4 +2819,3 @@ main (int ac, char **av) } #endif /* defined TEST */ - diff --git a/source3/modules/getdate.y b/source3/modules/getdate.y index edfb9d5ad7..21c01b896b 100644 --- a/source3/modules/getdate.y +++ b/source3/modules/getdate.y @@ -157,9 +157,6 @@ typedef struct #define YYLEX_PARAM parm #define YYPARSE_PARAM parm -static int yyerror (); -static int yylex (); - %} /* We want a reentrant parser. */ @@ -174,6 +171,13 @@ static int yylex (); textint textintval; } +%{ + +static int yyerror(const char *); +static int yylex(YYSTYPE *, parser_control *); + +%} + %token tAGO tDST %token tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tLOCAL_ZONE tMERIDIAN @@ -449,13 +453,13 @@ o_merid: #include "modules/getdate.h" #ifndef gmtime -struct tm *gmtime (); +struct tm *gmtime (const time_t *); #endif #ifndef localtime -struct tm *localtime (); +struct tm *localtime (const time_t *); #endif #ifndef mktime -time_t mktime (); +time_t mktime (struct tm *); #endif static table const meridian_table[] = @@ -863,7 +867,7 @@ yylex (YYSTYPE *lvalp, parser_control *pc) /* Do nothing if the parser reports an error. */ static int -yyerror (char *s ATTRIBUTE_UNUSED) +yyerror (const char *s ATTRIBUTE_UNUSED) { return 0; } -- cgit From 70874ceed92c60a2c016ea05507b0fa273f1d853 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Mon, 15 Dec 2008 23:13:26 -0800 Subject: s3: Fix "differing signedness" build warnings --- source3/rpc_parse/parse_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 169e5cb560..7d1d00a373 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -152,7 +152,7 @@ bool smb_io_dom_sid(const char *desc, DOM_SID *sid, prs_struct *ps, int depth) if(!prs_uint8 ("sid_rev_num", ps, depth, &sid->sid_rev_num)) return False; - if(!prs_uint8 ("num_auths ", ps, depth, &sid->num_auths)) + if(!prs_uint8 ("num_auths ", ps, depth, (uint8 *)&sid->num_auths)) return False; for (i = 0; i < 6; i++) -- cgit From 2f17be1f57b895b0e37e0a3d77d2ffea4d34d340 Mon Sep 17 00:00:00 2001 From: Dan Sledz Date: Mon, 15 Dec 2008 17:12:49 -0800 Subject: s3: Use DEBUGADD instead of DEBUG to avoid printing the header --- source3/lib/util_sock.c | 5 +++-- source3/rpc_parse/parse_prs.c | 52 +++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 605bbf1fb6..7fe8ed82a2 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -368,13 +368,14 @@ static void print_socket_options(int s) * leak in SCO Openserver 5.0 */ /* reported on samba-technical --jerry */ if ( DEBUGLEVEL >= 5 ) { + DEBUG(5,("Socket options:\n")); for (; p->name != NULL; p++) { if (getsockopt(s, p->level, p->option, (void *)&value, &vlen) == -1) { - DEBUG(5,("Could not test socket option %s.\n", + DEBUGADD(5,("\tCould not test socket option %s.\n", p->name)); } else { - DEBUG(5,("socket option %s = %d\n", + DEBUGADD(5,("\t%s = %d\n", p->name,value)); } } diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index acc0cc88ef..d549265fa1 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -629,7 +629,7 @@ bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) else SCVAL(q,0,*data8); - DEBUG(5,("%s%04x %s: %02x\n", tab_depth(5,depth), ps->data_offset, name, *data8)); + DEBUGADD(5,("%s%04x %s: %02x\n", tab_depth(5,depth), ps->data_offset, name, *data8)); ps->data_offset += 1; @@ -694,7 +694,7 @@ bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16) SSVAL(q,0,*data16); } - DEBUG(5,("%s%04x %s: %04x\n", tab_depth(5,depth), ps->data_offset, name, *data16)); + DEBUGADD(5,("%s%04x %s: %04x\n", tab_depth(5,depth), ps->data_offset, name, *data16)); ps->data_offset += sizeof(uint16); @@ -723,7 +723,7 @@ bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32) SIVAL(q,0,*data32); } - DEBUG(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); + DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); ps->data_offset += sizeof(uint32); @@ -752,7 +752,7 @@ bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32) SIVALS(q,0,*data32); } - DEBUG(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); + DEBUGADD(5,("%s%04x %s: %08x\n", tab_depth(5,depth), ps->data_offset, name, *data32)); ps->data_offset += sizeof(int32); @@ -781,7 +781,7 @@ bool prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status) SIVAL(q,0,NT_STATUS_V(*status)); } - DEBUG(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, + DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, nt_errstr(*status))); ps->data_offset += sizeof(uint32); @@ -811,7 +811,7 @@ bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *st SIVAL(q,0,NT_STATUS_V(*status)); } - DEBUG(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, + DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, dcerpc_errstr(debug_ctx(), NT_STATUS_V(*status)))); ps->data_offset += sizeof(uint32); @@ -842,7 +842,7 @@ bool prs_werror(const char *name, prs_struct *ps, int depth, WERROR *status) SIVAL(q,0,W_ERROR_V(*status)); } - DEBUG(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, + DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, win_errstr(*status))); ps->data_offset += sizeof(uint32); @@ -870,14 +870,14 @@ bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint SCVAL(q, i, data8s[i]); } - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset ,name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset ,name)); if (charmode) print_asc(5, (unsigned char*)data8s, len); else { for (i = 0; i < len; i++) - DEBUG(5,("%02x ", data8s[i])); + DEBUGADD(5,("%02x ", data8s[i])); } - DEBUG(5,("\n")); + DEBUGADD(5,("\n")); ps->data_offset += len; @@ -913,14 +913,14 @@ bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uin } } - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); if (charmode) print_asc(5, (unsigned char*)data16s, 2*len); else { for (i = 0; i < len; i++) - DEBUG(5,("%04x ", data16s[i])); + DEBUGADD(5,("%04x ", data16s[i])); } - DEBUG(5,("\n")); + DEBUGADD(5,("\n")); ps->data_offset += (len * sizeof(uint16)); @@ -955,14 +955,14 @@ static void dbg_rw_punival(bool charmode, const char *name, int depth, prs_struc } } - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); if (charmode) print_asc(5, (unsigned char*)out_buf, 2*len); else { for (i = 0; i < len; i++) - DEBUG(5,("%04x ", out_buf[i])); + DEBUGADD(5,("%04x ", out_buf[i])); } - DEBUG(5,("\n")); + DEBUGADD(5,("\n")); } /****************************************************************** @@ -1010,14 +1010,14 @@ bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uin } } - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); if (charmode) print_asc(5, (unsigned char*)data32s, 4*len); else { for (i = 0; i < len; i++) - DEBUG(5,("%08x ", data32s[i])); + DEBUGADD(5,("%08x ", data32s[i])); } - DEBUG(5,("\n")); + DEBUGADD(5,("\n")); ps->data_offset += (len * sizeof(uint32)); @@ -1078,7 +1078,7 @@ bool prs_string2(bool charmode, const char *name, prs_struct *ps, int depth, STR } else { str->buffer = NULL; /* Return early to ensure Coverity isn't confused. */ - DEBUG(5,("%s%04x %s: \n", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: \n", tab_depth(5,depth), ps->data_offset, name)); return True; } } @@ -1091,14 +1091,14 @@ bool prs_string2(bool charmode, const char *name, prs_struct *ps, int depth, STR SCVAL(q, i, str->buffer[i]); } - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); if (charmode) print_asc(5, (unsigned char*)str->buffer, str->str_str_len); else { for (i = 0; i < str->str_str_len; i++) DEBUG(5,("%02x ", str->buffer[i])); } - DEBUG(5,("\n")); + DEBUGADD(5,("\n")); ps->data_offset += str->str_str_len; @@ -1227,9 +1227,9 @@ bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str) len++; - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); print_asc(5, (unsigned char*)start, 2*len); - DEBUG(5, ("\n")); + DEBUGADD(5, ("\n")); } else { /* unmarshalling */ @@ -1284,9 +1284,9 @@ bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str) str->buffer[len++] = '\0'; } - DEBUG(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); + DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); print_asc(5, (unsigned char*)str->buffer, 2*len); - DEBUG(5, ("\n")); + DEBUGADD(5, ("\n")); } /* set the offset in the prs_struct; 'len' points to the -- cgit From 8891b2b0215a3609fcc8c5f9aa3e2fbcf05c6290 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 15 Dec 2008 16:47:38 +0100 Subject: s3:net_status: use dbwrap to open sessionid.tdb metze --- source3/utils/net_status.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/source3/utils/net_status.c b/source3/utils/net_status.c index 4e355e48b3..4e4debda5e 100644 --- a/source3/utils/net_status.c +++ b/source3/utils/net_status.c @@ -28,16 +28,15 @@ int net_status_usage(struct net_context *c, int argc, const char **argv) return -1; } -static int show_session(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *state) +static int show_session(struct db_record *rec, void *private_data) { - bool *parseable = (bool *)state; + bool *parseable = (bool *)private_data; struct sessionid sessionid; - if (dbuf.dsize != sizeof(sessionid)) + if (rec->value.dsize != sizeof(sessionid)) return 0; - memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); + memcpy(&sessionid, rec->value.dptr, sizeof(sessionid)); if (!process_exists(sessionid.pid)) { return 0; @@ -60,7 +59,7 @@ static int show_session(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, static int net_status_sessions(struct net_context *c, int argc, const char **argv) { - TDB_CONTEXT *tdb; + struct db_context *db; bool parseable; if (c->display_usage) { @@ -87,16 +86,15 @@ static int net_status_sessions(struct net_context *c, int argc, const char **arg "------------------------\n"); } - tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, - TDB_DEFAULT, O_RDONLY, 0); - - if (tdb == NULL) { + db = db_open(NULL, lock_path("sessionid.tdb"), 0, + TDB_CLEAR_IF_FIRST, O_RDONLY, 0644); + if (db == NULL) { d_fprintf(stderr, "%s not initialised\n", lock_path("sessionid.tdb")); return -1; } - tdb_traverse(tdb, show_session, &parseable); - tdb_close(tdb); + db->traverse_read(db, show_session, &parseable); + TALLOC_FREE(db); return 0; } @@ -126,16 +124,15 @@ struct sessionids { struct sessionid *entries; }; -static int collect_pid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void *state) +static int collect_pid(struct db_record *rec, void *private_data) { - struct sessionids *ids = (struct sessionids *)state; + struct sessionids *ids = (struct sessionids *)private_data; struct sessionid sessionid; - if (dbuf.dsize != sizeof(sessionid)) + if (rec->value.dsize != sizeof(sessionid)) return 0; - memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); + memcpy(&sessionid, rec->value.dptr, sizeof(sessionid)); if (!process_exists(sessionid.pid)) return 0; @@ -189,21 +186,20 @@ static int show_share_parseable(struct db_record *rec, static int net_status_shares_parseable(struct net_context *c, int argc, const char **argv) { struct sessionids ids; - TDB_CONTEXT *tdb; + struct db_context *db; ids.num_entries = 0; ids.entries = NULL; - tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, - TDB_DEFAULT, O_RDONLY, 0); - - if (tdb == NULL) { + db = db_open(NULL, lock_path("sessionid.tdb"), 0, + TDB_CLEAR_IF_FIRST, O_RDONLY, 0644); + if (db == NULL) { d_fprintf(stderr, "%s not initialised\n", lock_path("sessionid.tdb")); return -1; } - tdb_traverse(tdb, collect_pid, &ids); - tdb_close(tdb); + db->traverse_read(db, collect_pid, &ids); + TALLOC_FREE(db); connections_forall(show_share_parseable, &ids); -- cgit From b876e1336bed52e0823e0e88381d223bd6aa95e4 Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 16 Dec 2008 09:04:32 +0100 Subject: docs: Fix typo in the idmap_ad manpage. Karolin --- docs-xml/manpages-3/idmap_ad.8.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs-xml/manpages-3/idmap_ad.8.xml b/docs-xml/manpages-3/idmap_ad.8.xml index fb0792eb9e..2622b7bfdb 100644 --- a/docs-xml/manpages-3/idmap_ad.8.xml +++ b/docs-xml/manpages-3/idmap_ad.8.xml @@ -23,8 +23,8 @@ extensions. This module implements only the "idmap" API, and is READONLY. Mappings must be provided in advance by the administrator by adding the posixAccount/posixGroup - classess and relative attribute/value pairs to the users and - groups objects in AD + classes and relative attribute/value pairs to the user and + group objects in the AD. @@ -34,7 +34,7 @@ range = low - high - Defines the available matching uid and gid range for which the + Defines the available matching UID and GID range for which the backend is authoritative. Note that the range acts as a filter. If specified any UID or GID stored in AD that fall outside the range is ignored and the corresponding map is discarded. @@ -47,7 +47,7 @@ Defines the schema that idmap_ad should use when querying Active Directory regarding user and group information. - This can either the RFC2307 schema support included + This can be either the RFC2307 schema support included in Windows 2003 R2 or the Service for Unix (SFU) schema. -- cgit From 46f530e42f42b860407696f4e4733ad88e69f1be Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 16 Dec 2008 11:18:45 +0100 Subject: docs: Remove comment about default backend. Karolin --- docs-xml/manpages-3/idmap_ad.8.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-xml/manpages-3/idmap_ad.8.xml b/docs-xml/manpages-3/idmap_ad.8.xml index 2622b7bfdb..9437d34000 100644 --- a/docs-xml/manpages-3/idmap_ad.8.xml +++ b/docs-xml/manpages-3/idmap_ad.8.xml @@ -58,8 +58,8 @@ EXAMPLES The following example shows how to retrieve idmappings from our principal and - and trusted AD domains. All is needed is to set default to yes. If trusted - domains are present id conflicts must be resolved beforehand, there is no + and trusted AD domains. If trusted domains are present id conflicts must be + resolved beforehand, there is no guarantee on the order conflicting mappings would be resolved at this point. This example also shows how to leave a small non conflicting range for local -- cgit From 6821d898d7ecf10c6a9359560c5cf1c50a812b62 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Tue, 16 Dec 2008 09:30:16 +0100 Subject: nsswitch: Move source3 files to top level dir. Don't move source4 files yet to not confuse git's rename tracking too much. --- .gitignore | 2 + nsswitch/libwbclient/Doxyfile | 1297 +++++++++ nsswitch/libwbclient/libwbclient.h | 46 + nsswitch/libwbclient/wbc_err_internal.h | 45 + nsswitch/libwbclient/wbc_guid.c | 104 + nsswitch/libwbclient/wbc_idmap.c | 468 ++++ nsswitch/libwbclient/wbc_pam.c | 1034 +++++++ nsswitch/libwbclient/wbc_pwd.c | 571 ++++ nsswitch/libwbclient/wbc_sid.c | 672 +++++ nsswitch/libwbclient/wbc_util.c | 672 +++++ nsswitch/libwbclient/wbclient.c | 157 ++ nsswitch/libwbclient/wbclient.h | 1187 ++++++++ nsswitch/libwbclient/wbclient_internal.h | 32 + nsswitch/pam_winbind.c | 3204 ++++++++++++++++++++++ nsswitch/pam_winbind.h | 169 ++ nsswitch/wb_common.c | 690 +++++ nsswitch/wbinfo.c | 1984 ++++++++++++++ nsswitch/winbind_client.h | 30 + nsswitch/winbind_krb5_locator.c | 411 +++ nsswitch/winbind_nss.h | 76 + nsswitch/winbind_nss_aix.c | 1076 ++++++++ nsswitch/winbind_nss_config.h | 70 + nsswitch/winbind_nss_freebsd.c | 79 + nsswitch/winbind_nss_hpux.h | 137 + nsswitch/winbind_nss_irix.c | 633 +++++ nsswitch/winbind_nss_irix.h | 42 + nsswitch/winbind_nss_linux.c | 1477 ++++++++++ nsswitch/winbind_nss_linux.h | 29 + nsswitch/winbind_nss_netbsd.c | 442 +++ nsswitch/winbind_nss_netbsd.h | 40 + nsswitch/winbind_nss_solaris.c | 654 +++++ nsswitch/winbind_nss_solaris.h | 85 + nsswitch/winbind_struct_protocol.h | 514 ++++ nsswitch/wins.c | 446 +++ source3/Makefile.in | 28 +- source3/configure.in | 38 +- source3/nsswitch/libwbclient/Doxyfile | 1297 --------- source3/nsswitch/libwbclient/libwbclient.h | 46 - source3/nsswitch/libwbclient/wbc_err_internal.h | 45 - source3/nsswitch/libwbclient/wbc_guid.c | 104 - source3/nsswitch/libwbclient/wbc_idmap.c | 468 ---- source3/nsswitch/libwbclient/wbc_pam.c | 1034 ------- source3/nsswitch/libwbclient/wbc_pwd.c | 571 ---- source3/nsswitch/libwbclient/wbc_sid.c | 672 ----- source3/nsswitch/libwbclient/wbc_util.c | 672 ----- source3/nsswitch/libwbclient/wbclient.c | 159 -- source3/nsswitch/libwbclient/wbclient.h | 1187 -------- source3/nsswitch/libwbclient/wbclient_internal.h | 32 - source3/nsswitch/pam_winbind.c | 3204 ---------------------- source3/nsswitch/pam_winbind.h | 170 -- source3/nsswitch/wb_common.c | 690 ----- source3/nsswitch/wbinfo.c | 1984 -------------- source3/nsswitch/winbind_client.h | 30 - source3/nsswitch/winbind_krb5_locator.c | 411 --- source3/nsswitch/winbind_nss.h | 76 - source3/nsswitch/winbind_nss_aix.c | 1077 -------- source3/nsswitch/winbind_nss_config.h | 69 - source3/nsswitch/winbind_nss_freebsd.c | 79 - source3/nsswitch/winbind_nss_hpux.h | 137 - source3/nsswitch/winbind_nss_irix.c | 633 ----- source3/nsswitch/winbind_nss_irix.h | 42 - source3/nsswitch/winbind_nss_linux.c | 1477 ---------- source3/nsswitch/winbind_nss_linux.h | 29 - source3/nsswitch/winbind_nss_netbsd.c | 442 --- source3/nsswitch/winbind_nss_netbsd.h | 40 - source3/nsswitch/winbind_nss_solaris.c | 654 ----- source3/nsswitch/winbind_nss_solaris.h | 85 - source3/nsswitch/winbind_struct_protocol.h | 516 ---- source3/nsswitch/wins.c | 446 --- source4/winbind/wb_samba3_protocol.c | 6 - 70 files changed, 18608 insertions(+), 18617 deletions(-) create mode 100644 nsswitch/libwbclient/Doxyfile create mode 100644 nsswitch/libwbclient/libwbclient.h create mode 100644 nsswitch/libwbclient/wbc_err_internal.h create mode 100644 nsswitch/libwbclient/wbc_guid.c create mode 100644 nsswitch/libwbclient/wbc_idmap.c create mode 100644 nsswitch/libwbclient/wbc_pam.c create mode 100644 nsswitch/libwbclient/wbc_pwd.c create mode 100644 nsswitch/libwbclient/wbc_sid.c create mode 100644 nsswitch/libwbclient/wbc_util.c create mode 100644 nsswitch/libwbclient/wbclient.c create mode 100644 nsswitch/libwbclient/wbclient.h create mode 100644 nsswitch/libwbclient/wbclient_internal.h create mode 100644 nsswitch/pam_winbind.c create mode 100644 nsswitch/pam_winbind.h create mode 100644 nsswitch/wb_common.c create mode 100644 nsswitch/wbinfo.c create mode 100644 nsswitch/winbind_client.h create mode 100644 nsswitch/winbind_krb5_locator.c create mode 100644 nsswitch/winbind_nss.h create mode 100644 nsswitch/winbind_nss_aix.c create mode 100644 nsswitch/winbind_nss_config.h create mode 100644 nsswitch/winbind_nss_freebsd.c create mode 100644 nsswitch/winbind_nss_hpux.h create mode 100644 nsswitch/winbind_nss_irix.c create mode 100644 nsswitch/winbind_nss_irix.h create mode 100644 nsswitch/winbind_nss_linux.c create mode 100644 nsswitch/winbind_nss_linux.h create mode 100644 nsswitch/winbind_nss_netbsd.c create mode 100644 nsswitch/winbind_nss_netbsd.h create mode 100644 nsswitch/winbind_nss_solaris.c create mode 100644 nsswitch/winbind_nss_solaris.h create mode 100644 nsswitch/winbind_struct_protocol.h create mode 100644 nsswitch/wins.c delete mode 100644 source3/nsswitch/libwbclient/Doxyfile delete mode 100644 source3/nsswitch/libwbclient/libwbclient.h delete mode 100644 source3/nsswitch/libwbclient/wbc_err_internal.h delete mode 100644 source3/nsswitch/libwbclient/wbc_guid.c delete mode 100644 source3/nsswitch/libwbclient/wbc_idmap.c delete mode 100644 source3/nsswitch/libwbclient/wbc_pam.c delete mode 100644 source3/nsswitch/libwbclient/wbc_pwd.c delete mode 100644 source3/nsswitch/libwbclient/wbc_sid.c delete mode 100644 source3/nsswitch/libwbclient/wbc_util.c delete mode 100644 source3/nsswitch/libwbclient/wbclient.c delete mode 100644 source3/nsswitch/libwbclient/wbclient.h delete mode 100644 source3/nsswitch/libwbclient/wbclient_internal.h delete mode 100644 source3/nsswitch/pam_winbind.c delete mode 100644 source3/nsswitch/pam_winbind.h delete mode 100644 source3/nsswitch/wb_common.c delete mode 100644 source3/nsswitch/wbinfo.c delete mode 100644 source3/nsswitch/winbind_client.h delete mode 100644 source3/nsswitch/winbind_krb5_locator.c delete mode 100644 source3/nsswitch/winbind_nss.h delete mode 100644 source3/nsswitch/winbind_nss_aix.c delete mode 100644 source3/nsswitch/winbind_nss_config.h delete mode 100644 source3/nsswitch/winbind_nss_freebsd.c delete mode 100644 source3/nsswitch/winbind_nss_hpux.h delete mode 100644 source3/nsswitch/winbind_nss_irix.c delete mode 100644 source3/nsswitch/winbind_nss_irix.h delete mode 100644 source3/nsswitch/winbind_nss_linux.c delete mode 100644 source3/nsswitch/winbind_nss_linux.h delete mode 100644 source3/nsswitch/winbind_nss_netbsd.c delete mode 100644 source3/nsswitch/winbind_nss_netbsd.h delete mode 100644 source3/nsswitch/winbind_nss_solaris.c delete mode 100644 source3/nsswitch/winbind_nss_solaris.h delete mode 100644 source3/nsswitch/winbind_struct_protocol.h delete mode 100644 source3/nsswitch/wins.c diff --git a/.gitignore b/.gitignore index e617400cc5..07058be52b 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,8 @@ examples/VFS/skel_transparent.so *.po *.pyc semantic.cache +nsswitch/libnss_winbind.so +nsswitch/libnss_wins.so source3/bin/* source3/config.cache source3/config.log diff --git a/nsswitch/libwbclient/Doxyfile b/nsswitch/libwbclient/Doxyfile new file mode 100644 index 0000000000..529a16fd6a --- /dev/null +++ b/nsswitch/libwbclient/Doxyfile @@ -0,0 +1,1297 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Samba + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = HEAD + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = dox + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = $(PWD)/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = *.c \ + *.h \ + *.idl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = include/includes.h \ + include/proto.h + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 1 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = . + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 3 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = YES + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = NO + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/nsswitch/libwbclient/libwbclient.h b/nsswitch/libwbclient/libwbclient.h new file mode 100644 index 0000000000..74cba7e796 --- /dev/null +++ b/nsswitch/libwbclient/libwbclient.h @@ -0,0 +1,46 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _LIBWBCLIENT_H +#define _LIBWBCLIENT_H + +/* Super header including necessary public and private header files + for building the wbclient library. __DO NOT__ define anything + in this file. Only include other headers. */ + +/* Winbind headers */ + +#include "nsswitch/winbind_nss_config.h" +#include "nsswitch/winbind_struct_protocol.h" + +#include + +/* Public headers */ + +#include "wbclient.h" + +/* Private headers */ + +#include "wbc_err_internal.h" +#include "wbclient_internal.h" + + +#endif /* _LIBWBCLIENT_H */ diff --git a/nsswitch/libwbclient/wbc_err_internal.h b/nsswitch/libwbclient/wbc_err_internal.h new file mode 100644 index 0000000000..83364b8cd9 --- /dev/null +++ b/nsswitch/libwbclient/wbc_err_internal.h @@ -0,0 +1,45 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WBC_ERR_INTERNAL_H +#define _WBC_ERR_INTERNAL_H + +/* Private macros */ + +#define BAIL_ON_WBC_ERROR(x) \ + do { \ + if (!WBC_ERROR_IS_OK(x)) { \ + goto done; \ + } \ + } while(0); + +#define BAIL_ON_PTR_ERROR(x, status) \ + do { \ + if ((x) == NULL) { \ + status = WBC_ERR_NO_MEMORY; \ + goto done; \ + } else { \ + status = WBC_ERR_SUCCESS; \ + } \ + } while (0); + + +#endif /* _WBC_ERR_INTERNAL_H */ diff --git a/nsswitch/libwbclient/wbc_guid.c b/nsswitch/libwbclient/wbc_guid.c new file mode 100644 index 0000000000..c343e24351 --- /dev/null +++ b/nsswitch/libwbclient/wbc_guid.c @@ -0,0 +1,104 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + +/* Convert a binary GUID to a character string */ +wbcErr wbcGuidToString(const struct wbcGuid *guid, + char **guid_string) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!guid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + *guid_string = talloc_asprintf(NULL, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + guid->time_low, guid->time_mid, + guid->time_hi_and_version, + guid->clock_seq[0], + guid->clock_seq[1], + guid->node[0], guid->node[1], + guid->node[2], guid->node[3], + guid->node[4], guid->node[5]); + BAIL_ON_PTR_ERROR((*guid_string), wbc_status); + + wbc_status = WBC_ERR_SUCCESS; + +done: + return wbc_status; +} + +/* @brief Convert a character string to a binary GUID */ +wbcErr wbcStringToGuid(const char *str, + struct wbcGuid *guid) +{ + uint32_t time_low; + uint32_t time_mid, time_hi_and_version; + uint32_t clock_seq[2]; + uint32_t node[6]; + int i; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!guid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (!str) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (11 == sscanf(str, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + &time_low, &time_mid, &time_hi_and_version, + &clock_seq[0], &clock_seq[1], + &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { + wbc_status = WBC_ERR_SUCCESS; + } else if (11 == sscanf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + &time_low, &time_mid, &time_hi_and_version, + &clock_seq[0], &clock_seq[1], + &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { + wbc_status = WBC_ERR_SUCCESS; + } + + BAIL_ON_WBC_ERROR(wbc_status); + + guid->time_low = time_low; + guid->time_mid = time_mid; + guid->time_hi_and_version = time_hi_and_version; + guid->clock_seq[0] = clock_seq[0]; + guid->clock_seq[1] = clock_seq[1]; + + for (i=0;i<6;i++) { + guid->node[i] = node[i]; + } + + wbc_status = WBC_ERR_SUCCESS; + +done: + return wbc_status; +} diff --git a/nsswitch/libwbclient/wbc_idmap.c b/nsswitch/libwbclient/wbc_idmap.c new file mode 100644 index 0000000000..5b2ab875f6 --- /dev/null +++ b/nsswitch/libwbclient/wbc_idmap.c @@ -0,0 +1,468 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + +/* Convert a Windows SID to a Unix uid, allocating an uid if needed */ +wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid) +{ + struct winbindd_request request; + struct winbindd_response response; + char *sid_string = NULL; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!sid || !puid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); + wbcFreeMemory(sid_string); + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_SID_TO_UID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + *puid = response.data.uid; + + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* Convert a Windows SID to a Unix uid if there already is a mapping */ +wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid, + uid_t *puid) +{ + return WBC_ERR_NOT_IMPLEMENTED; +} + +/* Convert a Unix uid to a Windows SID, allocating a SID if needed */ +wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + + if (!sid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.uid = uid; + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_UID_TO_SID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + wbc_status = wbcStringToSid(response.data.sid.sid, sid); + BAIL_ON_WBC_ERROR(wbc_status); + +done: + return wbc_status; +} + +/* Convert a Unix uid to a Windows SID if there already is a mapping */ +wbcErr wbcQueryUidToSid(uid_t uid, + struct wbcDomainSid *sid) +{ + return WBC_ERR_NOT_IMPLEMENTED; +} + +/** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed + * + * @param *sid Pointer to the domain SID to be resolved + * @param *pgid Pointer to the resolved gid_t value + * + * @return #wbcErr + * + **/ + +wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *sid_string = NULL; + + if (!sid || !pgid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); + wbcFreeMemory(sid_string); + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_SID_TO_GID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + *pgid = response.data.gid; + + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* Convert a Windows SID to a Unix gid if there already is a mapping */ + +wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid, + gid_t *pgid) +{ + return WBC_ERR_NOT_IMPLEMENTED; +} + +/* Convert a Unix gid to a Windows SID, allocating a SID if needed */ +wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!sid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.gid = gid; + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_GID_TO_SID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + wbc_status = wbcStringToSid(response.data.sid.sid, sid); + BAIL_ON_WBC_ERROR(wbc_status); + +done: + return wbc_status; +} + +/* Convert a Unix gid to a Windows SID if there already is a mapping */ +wbcErr wbcQueryGidToSid(gid_t gid, + struct wbcDomainSid *sid) +{ + return WBC_ERR_NOT_IMPLEMENTED; +} + +/* Obtain a new uid from Winbind */ +wbcErr wbcAllocateUid(uid_t *puid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!puid) + return WBC_ERR_INVALID_PARAM; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_ALLOCATE_UID, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Copy out result */ + *puid = response.data.uid; + + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* Obtain a new gid from Winbind */ +wbcErr wbcAllocateGid(gid_t *pgid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!pgid) + return WBC_ERR_INVALID_PARAM; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_ALLOCATE_GID, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Copy out result */ + *pgid = response.data.gid; + + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* we can't include smb.h here... */ +#define _ID_TYPE_UID 1 +#define _ID_TYPE_GID 2 + +/* Set an user id mapping */ +wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *sid_string = NULL; + + if (!sid) { + return WBC_ERR_INVALID_PARAM; + } + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + request.data.dual_idmapset.id = uid; + request.data.dual_idmapset.type = _ID_TYPE_UID; + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.dual_idmapset.sid, sid_string, + sizeof(request.data.dual_idmapset.sid)-1); + wbcFreeMemory(sid_string); + + wbc_status = wbcRequestResponse(WINBINDD_SET_MAPPING, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Set a group id mapping */ +wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *sid_string = NULL; + + if (!sid) { + return WBC_ERR_INVALID_PARAM; + } + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + request.data.dual_idmapset.id = gid; + request.data.dual_idmapset.type = _ID_TYPE_GID; + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.dual_idmapset.sid, sid_string, + sizeof(request.data.dual_idmapset.sid)-1); + wbcFreeMemory(sid_string); + + wbc_status = wbcRequestResponse(WINBINDD_SET_MAPPING, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Remove a user id mapping */ +wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *sid_string = NULL; + + if (!sid) { + return WBC_ERR_INVALID_PARAM; + } + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + request.data.dual_idmapset.id = uid; + request.data.dual_idmapset.type = _ID_TYPE_UID; + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.dual_idmapset.sid, sid_string, + sizeof(request.data.dual_idmapset.sid)-1); + wbcFreeMemory(sid_string); + + wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Remove a group id mapping */ +wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *sid_string = NULL; + + if (!sid) { + return WBC_ERR_INVALID_PARAM; + } + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + request.data.dual_idmapset.id = gid; + request.data.dual_idmapset.type = _ID_TYPE_GID; + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.dual_idmapset.sid, sid_string, + sizeof(request.data.dual_idmapset.sid)-1); + wbcFreeMemory(sid_string); + + wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Set the highwater mark for allocated uids. */ +wbcErr wbcSetUidHwm(uid_t uid_hwm) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + request.data.dual_idmapset.id = uid_hwm; + request.data.dual_idmapset.type = _ID_TYPE_UID; + + wbc_status = wbcRequestResponse(WINBINDD_SET_HWM, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Set the highwater mark for allocated gids. */ +wbcErr wbcSetGidHwm(gid_t gid_hwm) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Make request */ + + request.data.dual_idmapset.id = gid_hwm; + request.data.dual_idmapset.type = _ID_TYPE_GID; + + wbc_status = wbcRequestResponse(WINBINDD_SET_HWM, + &request, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c new file mode 100644 index 0000000000..92c6643631 --- /dev/null +++ b/nsswitch/libwbclient/wbc_pam.c @@ -0,0 +1,1034 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + Copyright (C) Guenther Deschner 2008 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + +/* Authenticate a username/password pair */ +wbcErr wbcAuthenticateUser(const char *username, + const char *password) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcAuthUserParams params; + + ZERO_STRUCT(params); + + params.account_name = username; + params.level = WBC_AUTH_USER_LEVEL_PLAIN; + params.password.plaintext = password; + + wbc_status = wbcAuthenticateUserEx(¶ms, NULL, NULL); + BAIL_ON_WBC_ERROR(wbc_status); + +done: + return wbc_status; +} + +static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx, + const struct winbindd_response *resp, + struct wbcAuthUserInfo **_i) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcAuthUserInfo *i; + struct wbcDomainSid domain_sid; + char *p; + uint32_t sn = 0; + uint32_t j; + + i = talloc(mem_ctx, struct wbcAuthUserInfo); + BAIL_ON_PTR_ERROR(i, wbc_status); + + i->user_flags = resp->data.auth.info3.user_flgs; + + i->account_name = talloc_strdup(i, resp->data.auth.info3.user_name); + BAIL_ON_PTR_ERROR(i->account_name, wbc_status); + i->user_principal= NULL; + i->full_name = talloc_strdup(i, resp->data.auth.info3.full_name); + BAIL_ON_PTR_ERROR(i->full_name, wbc_status); + i->domain_name = talloc_strdup(i, resp->data.auth.info3.logon_dom); + BAIL_ON_PTR_ERROR(i->domain_name, wbc_status); + i->dns_domain_name= NULL; + + i->acct_flags = resp->data.auth.info3.acct_flags; + memcpy(i->user_session_key, + resp->data.auth.user_session_key, + sizeof(i->user_session_key)); + memcpy(i->lm_session_key, + resp->data.auth.first_8_lm_hash, + sizeof(i->lm_session_key)); + + i->logon_count = resp->data.auth.info3.logon_count; + i->bad_password_count = resp->data.auth.info3.bad_pw_count; + + i->logon_time = resp->data.auth.info3.logon_time; + i->logoff_time = resp->data.auth.info3.logoff_time; + i->kickoff_time = resp->data.auth.info3.kickoff_time; + i->pass_last_set_time = resp->data.auth.info3.pass_last_set_time; + i->pass_can_change_time = resp->data.auth.info3.pass_can_change_time; + i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time; + + i->logon_server = talloc_strdup(i, resp->data.auth.info3.logon_srv); + BAIL_ON_PTR_ERROR(i->logon_server, wbc_status); + i->logon_script = talloc_strdup(i, resp->data.auth.info3.logon_script); + BAIL_ON_PTR_ERROR(i->logon_script, wbc_status); + i->profile_path = talloc_strdup(i, resp->data.auth.info3.profile_path); + BAIL_ON_PTR_ERROR(i->profile_path, wbc_status); + i->home_directory= talloc_strdup(i, resp->data.auth.info3.home_dir); + BAIL_ON_PTR_ERROR(i->home_directory, wbc_status); + i->home_drive = talloc_strdup(i, resp->data.auth.info3.dir_drive); + BAIL_ON_PTR_ERROR(i->home_drive, wbc_status); + + i->num_sids = 2; + i->num_sids += resp->data.auth.info3.num_groups; + i->num_sids += resp->data.auth.info3.num_other_sids; + + i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids); + BAIL_ON_PTR_ERROR(i->sids, wbc_status); + + wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid, + &domain_sid); + BAIL_ON_WBC_ERROR(wbc_status); + +#define _SID_COMPOSE(s, d, r, a) { \ + (s).sid = d; \ + if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \ + (s).sid.sub_auths[(s).sid.num_auths++] = r; \ + } else { \ + wbc_status = WBC_ERR_INVALID_SID; \ + BAIL_ON_WBC_ERROR(wbc_status); \ + } \ + (s).attributes = a; \ +} while (0) + + sn = 0; + _SID_COMPOSE(i->sids[sn], domain_sid, + resp->data.auth.info3.user_rid, + 0); + sn++; + _SID_COMPOSE(i->sids[sn], domain_sid, + resp->data.auth.info3.group_rid, + 0); + sn++; + + p = (char *)resp->extra_data.data; + if (!p) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + + for (j=0; j < resp->data.auth.info3.num_groups; j++) { + uint32_t rid; + uint32_t attrs; + int ret; + char *s = p; + char *e = strchr(p, '\n'); + if (!e) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + e[0] = '\0'; + p = &e[1]; + + ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs); + if (ret != 2) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + + _SID_COMPOSE(i->sids[sn], domain_sid, + rid, attrs); + sn++; + } + + for (j=0; j < resp->data.auth.info3.num_other_sids; j++) { + uint32_t attrs; + int ret; + char *s = p; + char *a; + char *e = strchr(p, '\n'); + if (!e) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + e[0] = '\0'; + p = &e[1]; + + e = strchr(s, ':'); + if (!e) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + e[0] = '\0'; + a = &e[1]; + + ret = sscanf(a, "0x%08X", + &attrs); + if (ret != 1) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = wbcStringToSid(s, &i->sids[sn].sid); + BAIL_ON_WBC_ERROR(wbc_status); + + i->sids[sn].attributes = attrs; + sn++; + } + + i->num_sids = sn; + + *_i = i; + i = NULL; +done: + talloc_free(i); + return wbc_status; +} + +static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx, + const struct winbindd_response *resp, + struct wbcAuthErrorInfo **_e) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcAuthErrorInfo *e; + + e = talloc(mem_ctx, struct wbcAuthErrorInfo); + BAIL_ON_PTR_ERROR(e, wbc_status); + + e->nt_status = resp->data.auth.nt_status; + e->pam_error = resp->data.auth.pam_error; + e->nt_string = talloc_strdup(e, resp->data.auth.nt_status_string); + BAIL_ON_PTR_ERROR(e->nt_string, wbc_status); + + e->display_string = talloc_strdup(e, resp->data.auth.error_string); + BAIL_ON_PTR_ERROR(e->display_string, wbc_status); + + *_e = e; + e = NULL; + +done: + talloc_free(e); + return wbc_status; +} + +static wbcErr wbc_create_password_policy_info(TALLOC_CTX *mem_ctx, + const struct winbindd_response *resp, + struct wbcUserPasswordPolicyInfo **_i) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcUserPasswordPolicyInfo *i; + + i = talloc(mem_ctx, struct wbcUserPasswordPolicyInfo); + BAIL_ON_PTR_ERROR(i, wbc_status); + + i->min_passwordage = resp->data.auth.policy.min_passwordage; + i->min_length_password = resp->data.auth.policy.min_length_password; + i->password_history = resp->data.auth.policy.password_history; + i->password_properties = resp->data.auth.policy.password_properties; + i->expire = resp->data.auth.policy.expire; + + *_i = i; + i = NULL; + +done: + talloc_free(i); + return wbc_status; +} + +static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx, + const struct winbindd_response *resp, + struct wbcLogonUserInfo **_i) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcLogonUserInfo *i; + + i = talloc_zero(mem_ctx, struct wbcLogonUserInfo); + BAIL_ON_PTR_ERROR(i, wbc_status); + + wbc_status = wbc_create_auth_info(i, resp, &i->info); + BAIL_ON_WBC_ERROR(wbc_status); + + if (resp->data.auth.krb5ccname) { + wbc_status = wbcAddNamedBlob(&i->num_blobs, + &i->blobs, + "krb5ccname", + 0, + (uint8_t *)resp->data.auth.krb5ccname, + strlen(resp->data.auth.krb5ccname)+1); + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (resp->data.auth.unix_username) { + wbc_status = wbcAddNamedBlob(&i->num_blobs, + &i->blobs, + "unix_username", + 0, + (uint8_t *)resp->data.auth.unix_username, + strlen(resp->data.auth.unix_username)+1); + BAIL_ON_WBC_ERROR(wbc_status); + } + + *_i = i; + i = NULL; +done: + if (!WBC_ERROR_IS_OK(wbc_status) && i) { + wbcFreeMemory(i->blobs); + } + + talloc_free(i); + return wbc_status; +} + +/* Authenticate with more detailed information */ +wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params, + struct wbcAuthUserInfo **info, + struct wbcAuthErrorInfo **error) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + int cmd = 0; + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (error) { + *error = NULL; + } + + if (!params) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (!params->account_name) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + switch (params->level) { + case WBC_AUTH_USER_LEVEL_PLAIN: + cmd = WINBINDD_PAM_AUTH; + request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_USER_SESSION_KEY | + WBFLAG_PAM_LMKEY; + + if (!params->password.plaintext) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->domain_name && params->domain_name[0]) { + /* We need to get the winbind separator :-( */ + struct winbindd_response sep_response; + + ZERO_STRUCT(sep_response); + + wbc_status = wbcRequestResponse(WINBINDD_INFO, + NULL, &sep_response); + BAIL_ON_WBC_ERROR(wbc_status); + + snprintf(request.data.auth.user, + sizeof(request.data.auth.user)-1, + "%s%c%s", + params->domain_name, + sep_response.data.info.winbind_separator, + params->account_name); + } else { + strncpy(request.data.auth.user, + params->account_name, + sizeof(request.data.auth.user)-1); + } + + strncpy(request.data.auth.pass, + params->password.plaintext, + sizeof(request.data.auth.pass)-1); + break; + + case WBC_AUTH_USER_LEVEL_HASH: + wbc_status = WBC_ERR_NOT_IMPLEMENTED; + BAIL_ON_WBC_ERROR(wbc_status); + break; + + case WBC_AUTH_USER_LEVEL_RESPONSE: + cmd = WINBINDD_PAM_AUTH_CRAP; + request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_USER_SESSION_KEY | + WBFLAG_PAM_LMKEY; + + if (params->password.response.lm_length && + !params->password.response.lm_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + if (params->password.response.lm_length == 0 && + params->password.response.lm_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->password.response.nt_length && + !params->password.response.nt_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + if (params->password.response.nt_length == 0&& + params->password.response.nt_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + strncpy(request.data.auth_crap.user, + params->account_name, + sizeof(request.data.auth_crap.user)-1); + if (params->domain_name) { + strncpy(request.data.auth_crap.domain, + params->domain_name, + sizeof(request.data.auth_crap.domain)-1); + } + if (params->workstation_name) { + strncpy(request.data.auth_crap.workstation, + params->workstation_name, + sizeof(request.data.auth_crap.workstation)-1); + } + + request.data.auth_crap.logon_parameters = + params->parameter_control; + + memcpy(request.data.auth_crap.chal, + params->password.response.challenge, + sizeof(request.data.auth_crap.chal)); + + request.data.auth_crap.lm_resp_len = + MIN(params->password.response.lm_length, + sizeof(request.data.auth_crap.lm_resp)); + request.data.auth_crap.nt_resp_len = + MIN(params->password.response.nt_length, + sizeof(request.data.auth_crap.nt_resp)); + if (params->password.response.lm_data) { + memcpy(request.data.auth_crap.lm_resp, + params->password.response.lm_data, + request.data.auth_crap.lm_resp_len); + } + if (params->password.response.nt_data) { + memcpy(request.data.auth_crap.nt_resp, + params->password.response.nt_data, + request.data.auth_crap.nt_resp_len); + } + break; + default: + break; + } + + if (cmd == 0) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->flags) { + request.flags |= params->flags; + } + + wbc_status = wbcRequestResponse(cmd, + &request, + &response); + if (response.data.auth.nt_status != 0) { + if (error) { + wbc_status = wbc_create_error_info(NULL, + &response, + error); + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = WBC_ERR_AUTH_ERROR; + BAIL_ON_WBC_ERROR(wbc_status); + } + BAIL_ON_WBC_ERROR(wbc_status); + + if (info) { + wbc_status = wbc_create_auth_info(NULL, + &response, + info); + BAIL_ON_WBC_ERROR(wbc_status); + } + +done: + if (response.extra_data.data) + free(response.extra_data.data); + + return wbc_status; +} + +/* Trigger a verification of the trust credentials of a specific domain */ +wbcErr wbcCheckTrustCredentials(const char *domain, + struct wbcAuthErrorInfo **error) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (domain) { + /* + * the current protocol doesn't support + * specifying a domain + */ + wbc_status = WBC_ERR_NOT_IMPLEMENTED; + BAIL_ON_WBC_ERROR(wbc_status); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC, + &request, + &response); + if (response.data.auth.nt_status != 0) { + if (error) { + wbc_status = wbc_create_error_info(NULL, + &response, + error); + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = WBC_ERR_AUTH_ERROR; + BAIL_ON_WBC_ERROR(wbc_status); + } + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Trigger an extended logoff notification to Winbind for a specific user */ +wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params, + struct wbcAuthErrorInfo **error) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + int i; + + /* validate input */ + + if (!params || !params->username) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if ((params->num_blobs > 0) && (params->blobs == NULL)) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + if ((params->num_blobs == 0) && (params->blobs != NULL)) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.logoff.user, params->username, + sizeof(request.data.logoff.user)-1); + + for (i=0; inum_blobs; i++) { + + if (strcasecmp(params->blobs[i].name, "ccfilename") == 0) { + if (params->blobs[i].blob.data) { + strncpy(request.data.logoff.krb5ccname, + (const char *)params->blobs[i].blob.data, + sizeof(request.data.logoff.krb5ccname) - 1); + } + continue; + } + + if (strcasecmp(params->blobs[i].name, "user_uid") == 0) { + if (params->blobs[i].blob.data) { + memcpy(&request.data.logoff.uid, + params->blobs[i].blob.data, + MIN(params->blobs[i].blob.length, + sizeof(request.data.logoff.uid))); + } + continue; + } + + if (strcasecmp(params->blobs[i].name, "flags") == 0) { + if (params->blobs[i].blob.data) { + memcpy(&request.flags, + params->blobs[i].blob.data, + MIN(params->blobs[i].blob.length, + sizeof(request.flags))); + } + continue; + } + } + + /* Send request */ + + wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF, + &request, + &response); + + /* Take the response above and return it to the caller */ + if (response.data.auth.nt_status != 0) { + if (error) { + wbc_status = wbc_create_error_info(NULL, + &response, + error); + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = WBC_ERR_AUTH_ERROR; + BAIL_ON_WBC_ERROR(wbc_status); + } + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Trigger a logoff notification to Winbind for a specific user */ +wbcErr wbcLogoffUser(const char *username, + uid_t uid, + const char *ccfilename) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + /* validate input */ + + if (!username) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.logoff.user, username, + sizeof(request.data.logoff.user)-1); + request.data.logoff.uid = uid; + + if (ccfilename) { + strncpy(request.data.logoff.krb5ccname, ccfilename, + sizeof(request.data.logoff.krb5ccname)-1); + } + + /* Send request */ + + wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF, + &request, + &response); + + /* Take the response above and return it to the caller */ + + done: + return wbc_status; +} + +/* Change a password for a user with more detailed information upon failure */ +wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params, + struct wbcAuthErrorInfo **error, + enum wbcPasswordChangeRejectReason *reject_reason, + struct wbcUserPasswordPolicyInfo **policy) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + int cmd = 0; + + /* validate input */ + + if (!params->account_name) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (error) { + *error = NULL; + } + + if (policy) { + *policy = NULL; + } + + if (reject_reason) { + *reject_reason = -1; + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + switch (params->level) { + case WBC_CHANGE_PASSWORD_LEVEL_PLAIN: + cmd = WINBINDD_PAM_CHAUTHTOK; + + if (!params->account_name) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + strncpy(request.data.chauthtok.user, params->account_name, + sizeof(request.data.chauthtok.user) - 1); + + if (params->old_password.plaintext) { + strncpy(request.data.chauthtok.oldpass, + params->old_password.plaintext, + sizeof(request.data.chauthtok.oldpass) - 1); + } + + if (params->new_password.plaintext) { + strncpy(request.data.chauthtok.newpass, + params->new_password.plaintext, + sizeof(request.data.chauthtok.newpass) - 1); + } + break; + + case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE: + cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP; + + if (!params->account_name || !params->domain_name) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->old_password.response.old_lm_hash_enc_length && + !params->old_password.response.old_lm_hash_enc_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->old_password.response.old_lm_hash_enc_length == 0 && + params->old_password.response.old_lm_hash_enc_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->old_password.response.old_nt_hash_enc_length && + !params->old_password.response.old_nt_hash_enc_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->old_password.response.old_nt_hash_enc_length == 0 && + params->old_password.response.old_nt_hash_enc_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->new_password.response.lm_length && + !params->new_password.response.lm_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->new_password.response.lm_length == 0 && + params->new_password.response.lm_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->new_password.response.nt_length && + !params->new_password.response.nt_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (params->new_password.response.nt_length == 0 && + params->new_password.response.nt_data) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + strncpy(request.data.chng_pswd_auth_crap.user, + params->account_name, + sizeof(request.data.chng_pswd_auth_crap.user) - 1); + + strncpy(request.data.chng_pswd_auth_crap.domain, + params->domain_name, + sizeof(request.data.chng_pswd_auth_crap.domain) - 1); + + if (params->new_password.response.nt_data) { + memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd, + params->new_password.response.nt_data, + request.data.chng_pswd_auth_crap.new_nt_pswd_len); + request.data.chng_pswd_auth_crap.new_nt_pswd_len = + params->new_password.response.nt_length; + } + + if (params->new_password.response.lm_data) { + memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd, + params->new_password.response.lm_data, + request.data.chng_pswd_auth_crap.new_lm_pswd_len); + request.data.chng_pswd_auth_crap.new_lm_pswd_len = + params->new_password.response.lm_length; + } + + if (params->old_password.response.old_nt_hash_enc_data) { + memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc, + params->old_password.response.old_nt_hash_enc_data, + request.data.chng_pswd_auth_crap.old_nt_hash_enc_len); + request.data.chng_pswd_auth_crap.old_nt_hash_enc_len = + params->old_password.response.old_nt_hash_enc_length; + } + + if (params->old_password.response.old_lm_hash_enc_data) { + memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, + params->old_password.response.old_lm_hash_enc_data, + request.data.chng_pswd_auth_crap.old_lm_hash_enc_len); + request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = + params->old_password.response.old_lm_hash_enc_length; + } + + break; + default: + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + break; + } + + if (cmd == 0) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Send request */ + + wbc_status = wbcRequestResponse(cmd, + &request, + &response); + if (WBC_ERROR_IS_OK(wbc_status)) { + goto done; + } + + /* Take the response above and return it to the caller */ + + if (response.data.auth.nt_status != 0) { + if (error) { + wbc_status = wbc_create_error_info(NULL, + &response, + error); + BAIL_ON_WBC_ERROR(wbc_status); + } + + } + + if (policy) { + wbc_status = wbc_create_password_policy_info(NULL, + &response, + policy); + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (reject_reason) { + *reject_reason = response.data.auth.reject_reason; + } + + wbc_status = WBC_ERR_PWD_CHANGE_FAILED; + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Change a password for a user */ +wbcErr wbcChangeUserPassword(const char *username, + const char *old_password, + const char *new_password) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcChangePasswordParams params; + + ZERO_STRUCT(params); + + params.account_name = username; + params.level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN; + params.old_password.plaintext = old_password; + params.new_password.plaintext = new_password; + + wbc_status = wbcChangeUserPasswordEx(¶ms, + NULL, + NULL, + NULL); + BAIL_ON_WBC_ERROR(wbc_status); + +done: + return wbc_status; +} + +/* Logon a User */ +wbcErr wbcLogonUser(const struct wbcLogonUserParams *params, + struct wbcLogonUserInfo **info, + struct wbcAuthErrorInfo **error, + struct wbcUserPasswordPolicyInfo **policy) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + int cmd = 0; + struct winbindd_request request; + struct winbindd_response response; + uint32_t i; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (info) { + *info = NULL; + } + if (error) { + *error = NULL; + } + if (policy) { + *policy = NULL; + } + + if (!params) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (!params->username) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + if ((params->num_blobs > 0) && (params->blobs == NULL)) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + if ((params->num_blobs == 0) && (params->blobs != NULL)) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + cmd = WINBINDD_PAM_AUTH; + request.flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_USER_SESSION_KEY | + WBFLAG_PAM_LMKEY; + + if (!params->password) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + strncpy(request.data.auth.user, + params->username, + sizeof(request.data.auth.user)-1); + + strncpy(request.data.auth.pass, + params->password, + sizeof(request.data.auth.pass)-1); + + for (i=0; inum_blobs; i++) { + + if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) { + if (params->blobs[i].blob.data) { + strncpy(request.data.auth.krb5_cc_type, + (const char *)params->blobs[i].blob.data, + sizeof(request.data.auth.krb5_cc_type) - 1); + } + continue; + } + + if (strcasecmp(params->blobs[i].name, "user_uid") == 0) { + if (params->blobs[i].blob.data) { + memcpy(&request.data.auth.uid, + params->blobs[i].blob.data, + MIN(sizeof(request.data.auth.uid), + params->blobs[i].blob.length)); + } + continue; + } + + if (strcasecmp(params->blobs[i].name, "flags") == 0) { + if (params->blobs[i].blob.data) { + uint32_t flags; + memcpy(&flags, + params->blobs[i].blob.data, + MIN(sizeof(flags), + params->blobs[i].blob.length)); + request.flags |= flags; + } + continue; + } + + if (strcasecmp(params->blobs[i].name, "membership_of") == 0) { + if (params->blobs[i].blob.data && + params->blobs[i].blob.data[0] > 0) { + strncpy(request.data.auth.require_membership_of_sid, + (const char *)params->blobs[i].blob.data, + sizeof(request.data.auth.require_membership_of_sid) - 1); + } + continue; + } + } + + wbc_status = wbcRequestResponse(cmd, + &request, + &response); + + if (response.data.auth.nt_status != 0) { + if (error) { + wbc_status = wbc_create_error_info(NULL, + &response, + error); + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = WBC_ERR_AUTH_ERROR; + BAIL_ON_WBC_ERROR(wbc_status); + } + BAIL_ON_WBC_ERROR(wbc_status); + + if (info) { + wbc_status = wbc_create_logon_info(NULL, + &response, + info); + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (policy) { + wbc_status = wbc_create_password_policy_info(NULL, + &response, + policy); + BAIL_ON_WBC_ERROR(wbc_status); + } + +done: + if (response.extra_data.data) + free(response.extra_data.data); + + return wbc_status; +} + +/* Authenticate a user with cached credentials */ +wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params, + struct wbcCredentialCacheInfo **info, + struct wbcAuthErrorInfo **error) +{ + return WBC_ERR_NOT_IMPLEMENTED; +} diff --git a/nsswitch/libwbclient/wbc_pwd.c b/nsswitch/libwbclient/wbc_pwd.c new file mode 100644 index 0000000000..cd945996c8 --- /dev/null +++ b/nsswitch/libwbclient/wbc_pwd.c @@ -0,0 +1,571 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + +/** @brief The maximum number of pwent structs to get from winbindd + * + */ +#define MAX_GETPWENT_USERS 500 + +/** @brief The maximum number of grent structs to get from winbindd + * + */ +#define MAX_GETGRENT_GROUPS 500 + +/** + * + **/ + +static struct passwd *copy_passwd_entry(struct winbindd_pw *p) +{ + struct passwd *pwd = NULL; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + pwd = talloc(NULL, struct passwd); + BAIL_ON_PTR_ERROR(pwd, wbc_status); + + pwd->pw_name = talloc_strdup(pwd,p->pw_name); + BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status); + + pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd); + BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status); + + pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos); + BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status); + + pwd->pw_shell = talloc_strdup(pwd, p->pw_shell); + BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status); + + pwd->pw_dir = talloc_strdup(pwd, p->pw_dir); + BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status); + + pwd->pw_uid = p->pw_uid; + pwd->pw_gid = p->pw_gid; + +done: + if (!WBC_ERROR_IS_OK(wbc_status)) { + talloc_free(pwd); + pwd = NULL; + } + + return pwd; +} + +/** + * + **/ + +static struct group *copy_group_entry(struct winbindd_gr *g, + char *mem_buf) +{ + struct group *grp = NULL; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + int i; + char *mem_p, *mem_q; + + grp = talloc(NULL, struct group); + BAIL_ON_PTR_ERROR(grp, wbc_status); + + grp->gr_name = talloc_strdup(grp, g->gr_name); + BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status); + + grp->gr_passwd = talloc_strdup(grp, g->gr_passwd); + BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status); + + grp->gr_gid = g->gr_gid; + + grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1); + + mem_p = mem_q = mem_buf; + for (i=0; inum_gr_mem && mem_p; i++) { + if ((mem_q = strchr(mem_p, ',')) != NULL) { + *mem_q = '\0'; + } + + grp->gr_mem[i] = talloc_strdup(grp, mem_p); + BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status); + + if (mem_q == NULL) { + i += 1; + break; + } + mem_p = mem_q + 1; + } + grp->gr_mem[i] = NULL; + + wbc_status = WBC_ERR_SUCCESS; + +done: + if (!WBC_ERROR_IS_OK(wbc_status)) { + talloc_free(grp); + grp = NULL; + } + + return grp; +} + +/* Fill in a struct passwd* for a domain user based on username */ +wbcErr wbcGetpwnam(const char *name, struct passwd **pwd) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + + if (!name || !pwd) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* dst is already null terminated from the memset above */ + + strncpy(request.data.username, name, sizeof(request.data.username)-1); + + wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + *pwd = copy_passwd_entry(&response.data.pw); + BAIL_ON_PTR_ERROR(*pwd, wbc_status); + + done: + return wbc_status; +} + +/* Fill in a struct passwd* for a domain user based on uid */ +wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + + if (!pwd) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.uid = uid; + + wbc_status = wbcRequestResponse(WINBINDD_GETPWUID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + *pwd = copy_passwd_entry(&response.data.pw); + BAIL_ON_PTR_ERROR(*pwd, wbc_status); + + done: + return wbc_status; +} + +/* Fill in a struct passwd* for a domain user based on username */ +wbcErr wbcGetgrnam(const char *name, struct group **grp) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (!name || !grp) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* dst is already null terminated from the memset above */ + + strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1); + + wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + *grp = copy_group_entry(&response.data.gr, + (char*)response.extra_data.data); + BAIL_ON_PTR_ERROR(*grp, wbc_status); + + done: + if (response.extra_data.data) + free(response.extra_data.data); + + return wbc_status; +} + +/* Fill in a struct passwd* for a domain user based on uid */ +wbcErr wbcGetgrgid(gid_t gid, struct group **grp) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (!grp) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + request.data.gid = gid; + + wbc_status = wbcRequestResponse(WINBINDD_GETGRGID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + *grp = copy_group_entry(&response.data.gr, + (char*)response.extra_data.data); + BAIL_ON_PTR_ERROR(*grp, wbc_status); + + done: + if (response.extra_data.data) + free(response.extra_data.data); + + return wbc_status; +} + +/** @brief Number of cached passwd structs + * + */ +static uint32_t pw_cache_size; + +/** @brief Position of the pwent context + * + */ +static uint32_t pw_cache_idx; + +/** @brief Winbindd response containing the passwd structs + * + */ +static struct winbindd_response pw_response; + +/* Reset the passwd iterator */ +wbcErr wbcSetpwent(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (pw_cache_size > 0) { + pw_cache_idx = pw_cache_size = 0; + if (pw_response.extra_data.data) { + free(pw_response.extra_data.data); + } + } + + ZERO_STRUCT(pw_response); + + wbc_status = wbcRequestResponse(WINBINDD_SETPWENT, + NULL, NULL); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Close the passwd iterator */ +wbcErr wbcEndpwent(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (pw_cache_size > 0) { + pw_cache_idx = pw_cache_size = 0; + if (pw_response.extra_data.data) { + free(pw_response.extra_data.data); + } + } + + wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT, + NULL, NULL); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Return the next struct passwd* entry from the pwent iterator */ +wbcErr wbcGetpwent(struct passwd **pwd) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_pw *wb_pw; + + /* If there's a cached result, return that. */ + if (pw_cache_idx < pw_cache_size) { + goto return_result; + } + + /* Otherwise, query winbindd for some entries. */ + + pw_cache_idx = 0; + + if (pw_response.extra_data.data) { + free(pw_response.extra_data.data); + ZERO_STRUCT(pw_response); + } + + ZERO_STRUCT(request); + request.data.num_entries = MAX_GETPWENT_USERS; + + wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request, + &pw_response); + + BAIL_ON_WBC_ERROR(wbc_status); + + pw_cache_size = pw_response.data.num_entries; + +return_result: + + wb_pw = (struct winbindd_pw *) pw_response.extra_data.data; + + *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]); + + BAIL_ON_PTR_ERROR(*pwd, wbc_status); + + pw_cache_idx++; + +done: + return wbc_status; +} + +/** @brief Number of cached group structs + * + */ +static uint32_t gr_cache_size; + +/** @brief Position of the grent context + * + */ +static uint32_t gr_cache_idx; + +/** @brief Winbindd response containing the group structs + * + */ +static struct winbindd_response gr_response; + +/* Reset the group iterator */ +wbcErr wbcSetgrent(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (gr_cache_size > 0) { + gr_cache_idx = gr_cache_size = 0; + if (gr_response.extra_data.data) { + free(gr_response.extra_data.data); + } + } + + ZERO_STRUCT(gr_response); + + wbc_status = wbcRequestResponse(WINBINDD_SETGRENT, + NULL, NULL); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Close the group iterator */ +wbcErr wbcEndgrent(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (gr_cache_size > 0) { + gr_cache_idx = gr_cache_size = 0; + if (gr_response.extra_data.data) { + free(gr_response.extra_data.data); + } + } + + wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT, + NULL, NULL); + BAIL_ON_WBC_ERROR(wbc_status); + + done: + return wbc_status; +} + +/* Return the next struct group* entry from the pwent iterator */ +wbcErr wbcGetgrent(struct group **grp) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_gr *wb_gr; + uint32_t mem_ofs; + + /* If there's a cached result, return that. */ + if (gr_cache_idx < gr_cache_size) { + goto return_result; + } + + /* Otherwise, query winbindd for some entries. */ + + gr_cache_idx = 0; + + if (gr_response.extra_data.data) { + free(gr_response.extra_data.data); + ZERO_STRUCT(gr_response); + } + + ZERO_STRUCT(request); + request.data.num_entries = MAX_GETGRENT_GROUPS; + + wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request, + &gr_response); + + BAIL_ON_WBC_ERROR(wbc_status); + + gr_cache_size = gr_response.data.num_entries; + +return_result: + + wb_gr = (struct winbindd_gr *) gr_response.extra_data.data; + + mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs + + gr_cache_size * sizeof(struct winbindd_gr); + + *grp = copy_group_entry(&wb_gr[gr_cache_idx], + ((char *)gr_response.extra_data.data)+mem_ofs); + + BAIL_ON_PTR_ERROR(*grp, wbc_status); + + gr_cache_idx++; + +done: + return wbc_status; +} + +/* Return the next struct group* entry from the pwent iterator */ +wbcErr wbcGetgrlist(struct group **grp) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_gr *wb_gr; + + /* If there's a cached result, return that. */ + if (gr_cache_idx < gr_cache_size) { + goto return_result; + } + + /* Otherwise, query winbindd for some entries. */ + + gr_cache_idx = 0; + + if (gr_response.extra_data.data) { + free(gr_response.extra_data.data); + ZERO_STRUCT(gr_response); + } + + ZERO_STRUCT(request); + request.data.num_entries = MAX_GETGRENT_GROUPS; + + wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request, + &gr_response); + + BAIL_ON_WBC_ERROR(wbc_status); + + gr_cache_size = gr_response.data.num_entries; + +return_result: + + wb_gr = (struct winbindd_gr *) gr_response.extra_data.data; + + *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL); + + BAIL_ON_PTR_ERROR(*grp, wbc_status); + + gr_cache_idx++; + +done: + return wbc_status; +} + +/* Return the unix group array belonging to the given user */ +wbcErr wbcGetGroups(const char *account, + uint32_t *num_groups, + gid_t **_groups) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + uint32_t i; + gid_t *groups = NULL; + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (!account) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Send request */ + + strncpy(request.data.username, account, sizeof(request.data.username)-1); + + wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + groups = talloc_array(NULL, gid_t, response.data.num_entries); + BAIL_ON_PTR_ERROR(groups, wbc_status); + + for (i = 0; i < response.data.num_entries; i++) { + groups[i] = ((gid_t *)response.extra_data.data)[i]; + } + + *num_groups = response.data.num_entries; + *_groups = groups; + groups = NULL; + + wbc_status = WBC_ERR_SUCCESS; + + done: + if (response.extra_data.data) { + free(response.extra_data.data); + } + if (groups) { + talloc_free(groups); + } + + return wbc_status; +} diff --git a/nsswitch/libwbclient/wbc_sid.c b/nsswitch/libwbclient/wbc_sid.c new file mode 100644 index 0000000000..e2157b9609 --- /dev/null +++ b/nsswitch/libwbclient/wbc_sid.c @@ -0,0 +1,672 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + + +/* Convert a binary SID to a character string */ +wbcErr wbcSidToString(const struct wbcDomainSid *sid, + char **sid_string) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uint32_t id_auth; + int i; + char *tmp = NULL; + + if (!sid) { + wbc_status = WBC_ERR_INVALID_SID; + BAIL_ON_WBC_ERROR(wbc_status); + } + + id_auth = sid->id_auth[5] + + (sid->id_auth[4] << 8) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + tmp = talloc_asprintf(NULL, "S-%d-%d", sid->sid_rev_num, id_auth); + BAIL_ON_PTR_ERROR(tmp, wbc_status); + + for (i=0; inum_auths; i++) { + char *tmp2; + tmp2 = talloc_asprintf_append(tmp, "-%u", sid->sub_auths[i]); + BAIL_ON_PTR_ERROR(tmp2, wbc_status); + + tmp = tmp2; + } + + *sid_string = tmp; + tmp = NULL; + + wbc_status = WBC_ERR_SUCCESS; + +done: + talloc_free(tmp); + + return wbc_status; +} + +/* Convert a character string to a binary SID */ +wbcErr wbcStringToSid(const char *str, + struct wbcDomainSid *sid) +{ + const char *p; + char *q; + uint32_t x; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!sid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Sanity check for either "S-" or "s-" */ + + if (!str + || (str[0]!='S' && str[0]!='s') + || (str[1]!='-')) + { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Get the SID revision number */ + + p = str+2; + x = (uint32_t)strtol(p, &q, 10); + if (x==0 || !q || *q!='-') { + wbc_status = WBC_ERR_INVALID_SID; + BAIL_ON_WBC_ERROR(wbc_status); + } + sid->sid_rev_num = (uint8_t)x; + + /* Next the Identifier Authority. This is stored in big-endian + in a 6 byte array. */ + + p = q+1; + x = (uint32_t)strtol(p, &q, 10); + if (!q || *q!='-') { + wbc_status = WBC_ERR_INVALID_SID; + BAIL_ON_WBC_ERROR(wbc_status); + } + sid->id_auth[5] = (x & 0x000000ff); + sid->id_auth[4] = (x & 0x0000ff00) >> 8; + sid->id_auth[3] = (x & 0x00ff0000) >> 16; + sid->id_auth[2] = (x & 0xff000000) >> 24; + sid->id_auth[1] = 0; + sid->id_auth[0] = 0; + + /* now read the the subauthorities */ + + p = q +1; + sid->num_auths = 0; + while (sid->num_auths < WBC_MAXSUBAUTHS) { + x=(uint32_t)strtoul(p, &q, 10); + if (p == q) + break; + if (q == NULL) { + wbc_status = WBC_ERR_INVALID_SID; + BAIL_ON_WBC_ERROR(wbc_status); + } + sid->sub_auths[sid->num_auths++] = x; + + if ((*q!='-') || (*q=='\0')) + break; + p = q + 1; + } + + /* IF we ended early, then the SID could not be converted */ + + if (q && *q!='\0') { + wbc_status = WBC_ERR_INVALID_SID; + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = WBC_ERR_SUCCESS; + +done: + return wbc_status; + +} + +/* Convert a domain and name to SID */ +wbcErr wbcLookupName(const char *domain, + const char *name, + struct wbcDomainSid *sid, + enum wbcSidType *name_type) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + if (!sid || !name_type) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* dst is already null terminated from the memset above */ + + strncpy(request.data.name.dom_name, domain, + sizeof(request.data.name.dom_name)-1); + strncpy(request.data.name.name, name, + sizeof(request.data.name.name)-1); + + wbc_status = wbcRequestResponse(WINBINDD_LOOKUPNAME, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + wbc_status = wbcStringToSid(response.data.sid.sid, sid); + BAIL_ON_WBC_ERROR(wbc_status); + + *name_type = (enum wbcSidType)response.data.sid.type; + + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* Convert a SID to a domain and name */ +wbcErr wbcLookupSid(const struct wbcDomainSid *sid, + char **pdomain, + char **pname, + enum wbcSidType *pname_type) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *sid_string = NULL; + char *domain = NULL; + char *name = NULL; + enum wbcSidType name_type = WBC_SID_NAME_USE_NONE; + + if (!sid) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* dst is already null terminated from the memset above */ + + wbc_status = wbcSidToString(sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); + wbcFreeMemory(sid_string); + + /* Make request */ + + wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Copy out result */ + + domain = talloc_strdup(NULL, response.data.name.dom_name); + BAIL_ON_PTR_ERROR(domain, wbc_status); + + name = talloc_strdup(NULL, response.data.name.name); + BAIL_ON_PTR_ERROR(name, wbc_status); + + name_type = (enum wbcSidType)response.data.name.type; + + wbc_status = WBC_ERR_SUCCESS; + + done: + if (WBC_ERROR_IS_OK(wbc_status)) { + if (pdomain != NULL) { + *pdomain = domain; + } + if (pname != NULL) { + *pname = name; + } + if (pname_type != NULL) { + *pname_type = name_type; + } + } + else { +#if 0 + /* + * Found by Coverity: In this particular routine we can't end + * up here with a non-NULL name. Further up there are just two + * exit paths that lead here, neither of which leave an + * allocated name. If you add more paths up there, re-activate + * this. + */ + if (name != NULL) { + talloc_free(name); + } +#endif + if (domain != NULL) { + talloc_free(domain); + } + } + + return wbc_status; +} + +/* Translate a collection of RIDs within a domain to names */ + +wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid, + int num_rids, + uint32_t *rids, + const char **pp_domain_name, + const char ***pnames, + enum wbcSidType **ptypes) +{ + size_t i, len, ridbuf_size; + char *ridlist; + char *p; + struct winbindd_request request; + struct winbindd_response response; + char *sid_string = NULL; + char *domain_name = NULL; + const char **names = NULL; + enum wbcSidType *types = NULL; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (!dom_sid || (num_rids == 0)) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = wbcSidToString(dom_sid, &sid_string); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); + wbcFreeMemory(sid_string); + + /* Even if all the Rids were of maximum 32bit values, + we would only have 11 bytes per rid in the final array + ("4294967296" + \n). Add one more byte for the + terminating '\0' */ + + ridbuf_size = (sizeof(char)*11) * num_rids + 1; + + ridlist = talloc_zero_array(NULL, char, ridbuf_size); + BAIL_ON_PTR_ERROR(ridlist, wbc_status); + + len = 0; + for (i=0; i0; i++) { + char ridstr[12]; + + len = strlen(ridlist); + p = ridlist + len; + + snprintf( ridstr, sizeof(ridstr)-1, "%u\n", rids[i]); + strncat(p, ridstr, ridbuf_size-len-1); + } + + request.extra_data.data = ridlist; + request.extra_len = strlen(ridlist)+1; + + wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS, + &request, + &response); + talloc_free(ridlist); + BAIL_ON_WBC_ERROR(wbc_status); + + domain_name = talloc_strdup(NULL, response.data.domain_name); + BAIL_ON_PTR_ERROR(domain_name, wbc_status); + + names = talloc_array(NULL, const char*, num_rids); + BAIL_ON_PTR_ERROR(names, wbc_status); + + types = talloc_array(NULL, enum wbcSidType, num_rids); + BAIL_ON_PTR_ERROR(types, wbc_status); + + p = (char *)response.extra_data.data; + + for (i=0; ipw_gecos); + BAIL_ON_PTR_ERROR(name, wbc_status); + } + + wbc_status = WBC_ERR_SUCCESS; + + done: + if (WBC_ERROR_IS_OK(wbc_status)) { + *pdomain = domain; + *pfullname = name; + *pname_type = name_type; + } else { + wbcFreeMemory(domain); + wbcFreeMemory(name); + } + + return wbc_status; +} diff --git a/nsswitch/libwbclient/wbc_util.c b/nsswitch/libwbclient/wbc_util.c new file mode 100644 index 0000000000..5c5034ee13 --- /dev/null +++ b/nsswitch/libwbclient/wbc_util.c @@ -0,0 +1,672 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007-2008 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + + + +/** @brief Ping winbindd to see if the daemon is running + * + * @return #wbcErr + **/ + +wbcErr wbcPing(void) +{ + struct winbindd_request request; + struct winbindd_response response; + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + return wbcRequestResponse(WINBINDD_PING, &request, &response); +} + +wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcInterfaceDetails *info; + struct wbcDomainInfo *domain = NULL; + struct winbindd_request request; + struct winbindd_response response; + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + info = talloc(NULL, struct wbcInterfaceDetails); + BAIL_ON_PTR_ERROR(info, wbc_status); + + /* first the interface version */ + wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response); + BAIL_ON_WBC_ERROR(wbc_status); + info->interface_version = response.data.interface_version; + + /* then the samba version and the winbind separator */ + wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + info->winbind_version = talloc_strdup(info, + response.data.info.samba_version); + BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status); + info->winbind_separator = response.data.info.winbind_separator; + + /* then the local netbios name */ + wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + info->netbios_name = talloc_strdup(info, + response.data.netbios_name); + BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status); + + /* then the local workgroup name */ + wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response); + BAIL_ON_WBC_ERROR(wbc_status); + + info->netbios_domain = talloc_strdup(info, + response.data.domain_name); + BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status); + + wbc_status = wbcDomainInfo(info->netbios_domain, &domain); + if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) { + /* maybe it's a standalone server */ + domain = NULL; + wbc_status = WBC_ERR_SUCCESS; + } else { + BAIL_ON_WBC_ERROR(wbc_status); + } + + if (domain) { + info->dns_domain = talloc_strdup(info, + domain->dns_name); + wbcFreeMemory(domain); + BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status); + } else { + info->dns_domain = NULL; + } + + *_details = info; + info = NULL; + + wbc_status = WBC_ERR_SUCCESS; + +done: + talloc_free(info); + return wbc_status; +} + + +/* Lookup the current status of a trusted domain */ +wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainInfo *info = NULL; + + if (!domain || !dinfo) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Initialize request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.domain_name, domain, + sizeof(request.domain_name)-1); + + wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + info = talloc(NULL, struct wbcDomainInfo); + BAIL_ON_PTR_ERROR(info, wbc_status); + + info->short_name = talloc_strdup(info, + response.data.domain_info.name); + BAIL_ON_PTR_ERROR(info->short_name, wbc_status); + + info->dns_name = talloc_strdup(info, + response.data.domain_info.alt_name); + BAIL_ON_PTR_ERROR(info->dns_name, wbc_status); + + wbc_status = wbcStringToSid(response.data.domain_info.sid, + &info->sid); + BAIL_ON_WBC_ERROR(wbc_status); + + if (response.data.domain_info.native_mode) + info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE; + if (response.data.domain_info.active_directory) + info->domain_flags |= WBC_DOMINFO_DOMAIN_AD; + if (response.data.domain_info.primary) + info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY; + + *dinfo = info; + + wbc_status = WBC_ERR_SUCCESS; + + done: + if (!WBC_ERROR_IS_OK(wbc_status)) { + talloc_free(info); + } + + return wbc_status; +} + + +/* Resolve a NetbiosName via WINS */ +wbcErr wbcResolveWinsByName(const char *name, char **ip) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *ipaddr; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + strncpy(request.data.winsreq, name, + sizeof(request.data.winsreq)-1); + + wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Display response */ + + ipaddr = talloc_strdup(NULL, response.data.winsresp); + BAIL_ON_PTR_ERROR(ipaddr, wbc_status); + + *ip = ipaddr; + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* Resolve an IP address via WINS into a NetbiosName */ +wbcErr wbcResolveWinsByIP(const char *ip, char **name) +{ + struct winbindd_request request; + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *name_str; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + strncpy(request.data.winsreq, ip, + sizeof(request.data.winsreq)-1); + + wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Display response */ + + name_str = talloc_strdup(NULL, response.data.winsresp); + BAIL_ON_PTR_ERROR(name_str, wbc_status); + + *name = name_str; + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/** + */ + +static wbcErr process_domain_info_string(TALLOC_CTX *ctx, + struct wbcDomainInfo *info, + char *info_string) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *r = NULL; + char *s = NULL; + + if (!info || !info_string) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + r = info_string; + + /* Short Name */ + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + info->short_name = talloc_strdup(ctx, r); + BAIL_ON_PTR_ERROR(info->short_name, wbc_status); + + + /* DNS Name */ + r = s; + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + info->dns_name = talloc_strdup(ctx, r); + BAIL_ON_PTR_ERROR(info->dns_name, wbc_status); + + /* SID */ + r = s; + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + wbc_status = wbcStringToSid(r, &info->sid); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Trust type */ + r = s; + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + if (strcmp(r, "None") == 0) { + info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE; + } else if (strcmp(r, "External") == 0) { + info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL; + } else if (strcmp(r, "Forest") == 0) { + info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST; + } else if (strcmp(r, "In Forest") == 0) { + info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST; + } else { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Transitive */ + r = s; + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + if (strcmp(r, "Yes") == 0) { + info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE; + } + + /* Incoming */ + r = s; + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + if (strcmp(r, "Yes") == 0) { + info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING; + } + + /* Outgoing */ + r = s; + if ((s = strchr(r, '\\')) == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + *s = '\0'; + s++; + + if (strcmp(r, "Yes") == 0) { + info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING; + } + + /* Online/Offline status */ + + r = s; + if (r == NULL) { + wbc_status = WBC_ERR_INVALID_RESPONSE; + BAIL_ON_WBC_ERROR(wbc_status); + } + if ( strcmp(r, "Offline") == 0) { + info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE; + } + + wbc_status = WBC_ERR_SUCCESS; + + done: + return wbc_status; +} + +/* Enumerate the domain trusts known by Winbind */ +wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains) +{ + struct winbindd_response response; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *p = NULL; + char *q = NULL; + char *extra_data = NULL; + int count = 0; + struct wbcDomainInfo *d_list = NULL; + int i = 0; + + *domains = NULL; + *num_domains = 0; + + ZERO_STRUCT(response); + + /* Send request */ + + wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM, + NULL, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + /* Decode the response */ + + p = (char *)response.extra_data.data; + + if (strlen(p) == 0) { + /* We should always at least get back our + own SAM domain */ + + wbc_status = WBC_ERR_DOMAIN_NOT_FOUND; + BAIL_ON_WBC_ERROR(wbc_status); + } + + /* Count number of domains */ + + count = 0; + while (p) { + count++; + + if ((q = strchr(p, '\n')) != NULL) + q++; + p = q; + } + + d_list = talloc_array(NULL, struct wbcDomainInfo, count); + BAIL_ON_PTR_ERROR(d_list, wbc_status); + + extra_data = strdup((char*)response.extra_data.data); + BAIL_ON_PTR_ERROR(extra_data, wbc_status); + + p = extra_data; + + /* Outer loop processes the list of domain information */ + + for (i=0; idc_name = talloc_strdup(dc, response.data.dc_name); + BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status); + + *dc_info = dc; + +done: + if (!WBC_ERROR_IS_OK(wbc_status)) { + talloc_free(dc); + } + + return wbc_status; +} + +static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx, + const struct winbindd_response *resp, + struct wbcDomainControllerInfoEx **_i) +{ + wbcErr wbc_status = WBC_ERR_SUCCESS; + struct wbcDomainControllerInfoEx *i; + struct wbcGuid guid; + + i = talloc(mem_ctx, struct wbcDomainControllerInfoEx); + BAIL_ON_PTR_ERROR(i, wbc_status); + + i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc); + BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status); + + i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address); + BAIL_ON_PTR_ERROR(i->dc_address, wbc_status); + + i->dc_address_type = resp->data.dsgetdcname.dc_address_type; + + wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid); + if (WBC_ERROR_IS_OK(wbc_status)) { + i->domain_guid = talloc(i, struct wbcGuid); + BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status); + + *i->domain_guid = guid; + } else { + i->domain_guid = NULL; + } + + i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name); + BAIL_ON_PTR_ERROR(i->domain_name, wbc_status); + + if (resp->data.dsgetdcname.forest_name[0] != '\0') { + i->forest_name = talloc_strdup(i, + resp->data.dsgetdcname.forest_name); + BAIL_ON_PTR_ERROR(i->forest_name, wbc_status); + } else { + i->forest_name = NULL; + } + + i->dc_flags = resp->data.dsgetdcname.dc_flags; + + if (resp->data.dsgetdcname.dc_site_name[0] != '\0') { + i->dc_site_name = talloc_strdup(i, + resp->data.dsgetdcname.dc_site_name); + BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status); + } else { + i->dc_site_name = NULL; + } + + if (resp->data.dsgetdcname.client_site_name[0] != '\0') { + i->client_site_name = talloc_strdup(i, + resp->data.dsgetdcname.client_site_name); + BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status); + } else { + i->client_site_name = NULL; + } + + *_i = i; + i = NULL; + +done: + talloc_free(i); + return wbc_status; +} + +/* Get extended domain controller information */ +wbcErr wbcLookupDomainControllerEx(const char *domain, + struct wbcGuid *guid, + const char *site, + uint32_t flags, + struct wbcDomainControllerInfoEx **dc_info) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct winbindd_request request; + struct winbindd_response response; + + /* validate input params */ + + if (!domain || !dc_info) { + wbc_status = WBC_ERR_INVALID_PARAM; + BAIL_ON_WBC_ERROR(wbc_status); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.dsgetdcname.flags = flags; + + strncpy(request.data.dsgetdcname.domain_name, domain, + sizeof(request.data.dsgetdcname.domain_name)-1); + + if (site) { + strncpy(request.data.dsgetdcname.site_name, site, + sizeof(request.data.dsgetdcname.site_name)-1); + } + + if (guid) { + char *str = NULL; + + wbc_status = wbcGuidToString(guid, &str); + BAIL_ON_WBC_ERROR(wbc_status); + + strncpy(request.data.dsgetdcname.domain_guid, str, + sizeof(request.data.dsgetdcname.domain_guid)-1); + + wbcFreeMemory(str); + } + + /* Send request */ + + wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME, + &request, + &response); + BAIL_ON_WBC_ERROR(wbc_status); + + if (dc_info) { + wbc_status = wbc_create_domain_controller_info_ex(NULL, + &response, + dc_info); + BAIL_ON_WBC_ERROR(wbc_status); + } + + wbc_status = WBC_ERR_SUCCESS; +done: + return wbc_status; +} + +/* Initialize a named blob and add to list of blobs */ +wbcErr wbcAddNamedBlob(size_t *num_blobs, + struct wbcNamedBlob **blobs, + const char *name, + uint32_t flags, + uint8_t *data, + size_t length) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcNamedBlob blob; + + *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob, + *(num_blobs)+1); + BAIL_ON_PTR_ERROR(*blobs, wbc_status); + + blob.name = talloc_strdup(*blobs, name); + BAIL_ON_PTR_ERROR(blob.name, wbc_status); + blob.flags = flags; + blob.blob.length = length; + blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length); + BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status); + + (*(blobs))[*num_blobs] = blob; + *(num_blobs) += 1; + + wbc_status = WBC_ERR_SUCCESS; +done: + if (!WBC_ERROR_IS_OK(wbc_status) && blobs) { + wbcFreeMemory(*blobs); + } + return wbc_status; +} diff --git a/nsswitch/libwbclient/wbclient.c b/nsswitch/libwbclient/wbclient.c new file mode 100644 index 0000000000..f5c72315f2 --- /dev/null +++ b/nsswitch/libwbclient/wbclient.c @@ -0,0 +1,157 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* Required Headers */ + +#include "libwbclient.h" + +/* From wb_common.c */ + +NSS_STATUS winbindd_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); + +/** @brief Wrapper around Winbind's send/receive API call + * + * @param cmd Winbind command operation to perform + * @param request Send structure + * @param response Receive structure + * + * @return #wbcErr + **/ + +/********************************************************************** + result == NSS_STATUS_UNAVAIL: winbind not around + result == NSS_STATUS_NOTFOUND: winbind around, but domain missing + + Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off + and when winbind return WINBINDD_ERROR. So the semantics of this + routine depends on winbind_on. Grepping for winbind_off I just + found 3 places where winbind is turned off, and this does not conflict + (as far as I have seen) with the callers of is_trusted_domains. + + --Volker +**********************************************************************/ + +wbcErr wbcRequestResponse(int cmd, + struct winbindd_request *request, + struct winbindd_response *response) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + NSS_STATUS nss_status; + + /* for some calls the request and/or response can be NULL */ + + nss_status = winbindd_request_response(cmd, request, response); + + switch (nss_status) { + case NSS_STATUS_SUCCESS: + wbc_status = WBC_ERR_SUCCESS; + break; + case NSS_STATUS_UNAVAIL: + wbc_status = WBC_ERR_WINBIND_NOT_AVAILABLE; + break; + case NSS_STATUS_NOTFOUND: + wbc_status = WBC_ERR_DOMAIN_NOT_FOUND; + break; + default: + wbc_status = WBC_ERR_NSS_ERROR; + break; + } + + return wbc_status; +} + +/** @brief Translate an error value into a string + * + * @param error + * + * @return a pointer to a static string + **/ +const char *wbcErrorString(wbcErr error) +{ + switch (error) { + case WBC_ERR_SUCCESS: + return "WBC_ERR_SUCCESS"; + case WBC_ERR_NOT_IMPLEMENTED: + return "WBC_ERR_NOT_IMPLEMENTED"; + case WBC_ERR_UNKNOWN_FAILURE: + return "WBC_ERR_UNKNOWN_FAILURE"; + case WBC_ERR_NO_MEMORY: + return "WBC_ERR_NO_MEMORY"; + case WBC_ERR_INVALID_SID: + return "WBC_ERR_INVALID_SID"; + case WBC_ERR_INVALID_PARAM: + return "WBC_ERR_INVALID_PARAM"; + case WBC_ERR_WINBIND_NOT_AVAILABLE: + return "WBC_ERR_WINBIND_NOT_AVAILABLE"; + case WBC_ERR_DOMAIN_NOT_FOUND: + return "WBC_ERR_DOMAIN_NOT_FOUND"; + case WBC_ERR_INVALID_RESPONSE: + return "WBC_ERR_INVALID_RESPONSE"; + case WBC_ERR_NSS_ERROR: + return "WBC_ERR_NSS_ERROR"; + case WBC_ERR_UNKNOWN_USER: + return "WBC_ERR_UNKNOWN_USER"; + case WBC_ERR_UNKNOWN_GROUP: + return "WBC_ERR_UNKNOWN_GROUP"; + case WBC_ERR_AUTH_ERROR: + return "WBC_ERR_AUTH_ERROR"; + case WBC_ERR_PWD_CHANGE_FAILED: + return "WBC_ERR_PWD_CHANGE_FAILED"; + } + + return "unknown wbcErr value"; +} + +/* Free library allocated memory */ +void wbcFreeMemory(void *p) +{ + if (p) + talloc_free(p); + + return; +} + +wbcErr wbcLibraryDetails(struct wbcLibraryDetails **_details) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcLibraryDetails *info; + + info = talloc(NULL, struct wbcLibraryDetails); + BAIL_ON_PTR_ERROR(info, wbc_status); + + info->major_version = WBCLIENT_MAJOR_VERSION; + info->minor_version = WBCLIENT_MINOR_VERSION; + info->vendor_version = talloc_strdup(info, + WBCLIENT_VENDOR_VERSION); + BAIL_ON_PTR_ERROR(info->vendor_version, wbc_status); + + *_details = info; + info = NULL; + + wbc_status = WBC_ERR_SUCCESS; + +done: + talloc_free(info); + return wbc_status; +} diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h new file mode 100644 index 0000000000..990cc52df7 --- /dev/null +++ b/nsswitch/libwbclient/wbclient.h @@ -0,0 +1,1187 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WBCLIENT_H +#define _WBCLIENT_H + +#include +#include + +/* Define error types */ + +/** + * @brief Status codes returned from wbc functions + **/ + +enum _wbcErrType { + WBC_ERR_SUCCESS = 0, /**< Successful completion **/ + WBC_ERR_NOT_IMPLEMENTED,/**< Function not implemented **/ + WBC_ERR_UNKNOWN_FAILURE,/**< General failure **/ + WBC_ERR_NO_MEMORY, /**< Memory allocation error **/ + WBC_ERR_INVALID_SID, /**< Invalid SID format **/ + WBC_ERR_INVALID_PARAM, /**< An Invalid parameter was supplied **/ + WBC_ERR_WINBIND_NOT_AVAILABLE, /**< Winbind daemon is not available **/ + WBC_ERR_DOMAIN_NOT_FOUND, /**< Domain is not trusted or cannot be found **/ + WBC_ERR_INVALID_RESPONSE, /**< Winbind returned an invalid response **/ + WBC_ERR_NSS_ERROR, /**< NSS_STATUS error **/ + WBC_ERR_AUTH_ERROR, /**< Authentication failed **/ + WBC_ERR_UNKNOWN_USER, /**< User account cannot be found */ + WBC_ERR_UNKNOWN_GROUP, /**< Group account cannot be found */ + WBC_ERR_PWD_CHANGE_FAILED /**< Password Change has failed */ +}; + +typedef enum _wbcErrType wbcErr; + +#define WBC_ERROR_IS_OK(x) ((x) == WBC_ERR_SUCCESS) + +const char *wbcErrorString(wbcErr error); + +/** + * @brief Some useful details about the wbclient library + * + * 0.1: Initial version + * 0.2: Added wbcRemoveUidMapping() + * Added wbcRemoveGidMapping() + **/ +#define WBCLIENT_MAJOR_VERSION 0 +#define WBCLIENT_MINOR_VERSION 2 +#define WBCLIENT_VENDOR_VERSION "Samba libwbclient" +struct wbcLibraryDetails { + uint16_t major_version; + uint16_t minor_version; + const char *vendor_version; +}; + +/** + * @brief Some useful details about the running winbindd + * + **/ +struct wbcInterfaceDetails { + uint32_t interface_version; + const char *winbind_version; + char winbind_separator; + const char *netbios_name; + const char *netbios_domain; + const char *dns_domain; +}; + +/* + * Data types used by the Winbind Client API + */ + +#ifndef WBC_MAXSUBAUTHS +#define WBC_MAXSUBAUTHS 15 /* max sub authorities in a SID */ +#endif + +/** + * @brief Windows Security Identifier + * + **/ + +struct wbcDomainSid { + uint8_t sid_rev_num; + uint8_t num_auths; + uint8_t id_auth[6]; + uint32_t sub_auths[WBC_MAXSUBAUTHS]; +}; + +/** + * @brief Security Identifier type + **/ + +enum wbcSidType { + WBC_SID_NAME_USE_NONE=0, + WBC_SID_NAME_USER=1, + WBC_SID_NAME_DOM_GRP=2, + WBC_SID_NAME_DOMAIN=3, + WBC_SID_NAME_ALIAS=4, + WBC_SID_NAME_WKN_GRP=5, + WBC_SID_NAME_DELETED=6, + WBC_SID_NAME_INVALID=7, + WBC_SID_NAME_UNKNOWN=8, + WBC_SID_NAME_COMPUTER=9 +}; + +/** + * @brief Security Identifier with attributes + **/ + +struct wbcSidWithAttr { + struct wbcDomainSid sid; + uint32_t attributes; +}; + +/* wbcSidWithAttr->attributes */ + +#define WBC_SID_ATTR_GROUP_MANDATORY 0x00000001 +#define WBC_SID_ATTR_GROUP_ENABLED_BY_DEFAULT 0x00000002 +#define WBC_SID_ATTR_GROUP_ENABLED 0x00000004 +#define WBC_SID_ATTR_GROUP_OWNER 0x00000008 +#define WBC_SID_ATTR_GROUP_USEFOR_DENY_ONLY 0x00000010 +#define WBC_SID_ATTR_GROUP_RESOURCE 0x20000000 +#define WBC_SID_ATTR_GROUP_LOGON_ID 0xC0000000 + +/** + * @brief Windows GUID + * + **/ + +struct wbcGuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq[2]; + uint8_t node[6]; +}; + +/** + * @brief Domain Information + **/ + +struct wbcDomainInfo { + char *short_name; + char *dns_name; + struct wbcDomainSid sid; + uint32_t domain_flags; + uint32_t trust_flags; + uint32_t trust_type; +}; + +/* wbcDomainInfo->domain_flags */ + +#define WBC_DOMINFO_DOMAIN_UNKNOWN 0x00000000 +#define WBC_DOMINFO_DOMAIN_NATIVE 0x00000001 +#define WBC_DOMINFO_DOMAIN_AD 0x00000002 +#define WBC_DOMINFO_DOMAIN_PRIMARY 0x00000004 +#define WBC_DOMINFO_DOMAIN_OFFLINE 0x00000008 + +/* wbcDomainInfo->trust_flags */ + +#define WBC_DOMINFO_TRUST_TRANSITIVE 0x00000001 +#define WBC_DOMINFO_TRUST_INCOMING 0x00000002 +#define WBC_DOMINFO_TRUST_OUTGOING 0x00000004 + +/* wbcDomainInfo->trust_type */ + +#define WBC_DOMINFO_TRUSTTYPE_NONE 0x00000000 +#define WBC_DOMINFO_TRUSTTYPE_FOREST 0x00000001 +#define WBC_DOMINFO_TRUSTTYPE_IN_FOREST 0x00000002 +#define WBC_DOMINFO_TRUSTTYPE_EXTERNAL 0x00000003 + + +/** + * @brief Auth User Parameters + **/ + +struct wbcAuthUserParams { + const char *account_name; + const char *domain_name; + const char *workstation_name; + + uint32_t flags; + + uint32_t parameter_control; + + enum wbcAuthUserLevel { + WBC_AUTH_USER_LEVEL_PLAIN = 1, + WBC_AUTH_USER_LEVEL_HASH = 2, + WBC_AUTH_USER_LEVEL_RESPONSE = 3 + } level; + union { + const char *plaintext; + struct { + uint8_t nt_hash[16]; + uint8_t lm_hash[16]; + } hash; + struct { + uint8_t challenge[8]; + uint32_t nt_length; + uint8_t *nt_data; + uint32_t lm_length; + uint8_t *lm_data; + } response; + } password; +}; + +/** + * @brief Generic Blob + **/ + +struct wbcBlob { + uint8_t *data; + size_t length; +}; + +/** + * @brief Named Blob + **/ + +struct wbcNamedBlob { + const char *name; + uint32_t flags; + struct wbcBlob blob; +}; + +/** + * @brief Logon User Parameters + **/ + +struct wbcLogonUserParams { + const char *username; + const char *password; + size_t num_blobs; + struct wbcNamedBlob *blobs; +}; + +/** + * @brief ChangePassword Parameters + **/ + +struct wbcChangePasswordParams { + const char *account_name; + const char *domain_name; + + uint32_t flags; + + enum wbcChangePasswordLevel { + WBC_CHANGE_PASSWORD_LEVEL_PLAIN = 1, + WBC_CHANGE_PASSWORD_LEVEL_RESPONSE = 2 + } level; + + union { + const char *plaintext; + struct { + uint32_t old_nt_hash_enc_length; + uint8_t *old_nt_hash_enc_data; + uint32_t old_lm_hash_enc_length; + uint8_t *old_lm_hash_enc_data; + } response; + } old_password; + union { + const char *plaintext; + struct { + uint32_t nt_length; + uint8_t *nt_data; + uint32_t lm_length; + uint8_t *lm_data; + } response; + } new_password; +}; + +/* wbcAuthUserParams->parameter_control */ + +#define WBC_MSV1_0_CLEARTEXT_PASSWORD_ALLOWED 0x00000002 +#define WBC_MSV1_0_UPDATE_LOGON_STATISTICS 0x00000004 +#define WBC_MSV1_0_RETURN_USER_PARAMETERS 0x00000008 +#define WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT 0x00000020 +#define WBC_MSV1_0_RETURN_PROFILE_PATH 0x00000200 +#define WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 0x00000800 + +/* wbcAuthUserParams->flags */ + +#define WBC_AUTH_PARAM_FLAGS_INTERACTIVE_LOGON 0x00000001 + +/** + * @brief Auth User Information + * + * Some of the strings are maybe NULL + **/ + +struct wbcAuthUserInfo { + uint32_t user_flags; + + char *account_name; + char *user_principal; + char *full_name; + char *domain_name; + char *dns_domain_name; + + uint32_t acct_flags; + uint8_t user_session_key[16]; + uint8_t lm_session_key[8]; + + uint16_t logon_count; + uint16_t bad_password_count; + + uint64_t logon_time; + uint64_t logoff_time; + uint64_t kickoff_time; + uint64_t pass_last_set_time; + uint64_t pass_can_change_time; + uint64_t pass_must_change_time; + + char *logon_server; + char *logon_script; + char *profile_path; + char *home_directory; + char *home_drive; + + /* + * the 1st one is the account sid + * the 2nd one is the primary_group sid + * followed by the rest of the groups + */ + uint32_t num_sids; + struct wbcSidWithAttr *sids; +}; + +/** + * @brief Logon User Information + * + * Some of the strings are maybe NULL + **/ + +struct wbcLogonUserInfo { + struct wbcAuthUserInfo *info; + size_t num_blobs; + struct wbcNamedBlob *blobs; +}; + +/* wbcAuthUserInfo->user_flags */ + +#define WBC_AUTH_USER_INFO_GUEST 0x00000001 +#define WBC_AUTH_USER_INFO_NOENCRYPTION 0x00000002 +#define WBC_AUTH_USER_INFO_CACHED_ACCOUNT 0x00000004 +#define WBC_AUTH_USER_INFO_USED_LM_PASSWORD 0x00000008 +#define WBC_AUTH_USER_INFO_EXTRA_SIDS 0x00000020 +#define WBC_AUTH_USER_INFO_SUBAUTH_SESSION_KEY 0x00000040 +#define WBC_AUTH_USER_INFO_SERVER_TRUST_ACCOUNT 0x00000080 +#define WBC_AUTH_USER_INFO_NTLMV2_ENABLED 0x00000100 +#define WBC_AUTH_USER_INFO_RESOURCE_GROUPS 0x00000200 +#define WBC_AUTH_USER_INFO_PROFILE_PATH_RETURNED 0x00000400 +#define WBC_AUTH_USER_INFO_GRACE_LOGON 0x01000000 + +/* wbcAuthUserInfo->acct_flags */ + +#define WBC_ACB_DISABLED 0x00000001 /* 1 User account disabled */ +#define WBC_ACB_HOMDIRREQ 0x00000002 /* 1 Home directory required */ +#define WBC_ACB_PWNOTREQ 0x00000004 /* 1 User password not required */ +#define WBC_ACB_TEMPDUP 0x00000008 /* 1 Temporary duplicate account */ +#define WBC_ACB_NORMAL 0x00000010 /* 1 Normal user account */ +#define WBC_ACB_MNS 0x00000020 /* 1 MNS logon user account */ +#define WBC_ACB_DOMTRUST 0x00000040 /* 1 Interdomain trust account */ +#define WBC_ACB_WSTRUST 0x00000080 /* 1 Workstation trust account */ +#define WBC_ACB_SVRTRUST 0x00000100 /* 1 Server trust account */ +#define WBC_ACB_PWNOEXP 0x00000200 /* 1 User password does not expire */ +#define WBC_ACB_AUTOLOCK 0x00000400 /* 1 Account auto locked */ +#define WBC_ACB_ENC_TXT_PWD_ALLOWED 0x00000800 /* 1 Encryped text password is allowed */ +#define WBC_ACB_SMARTCARD_REQUIRED 0x00001000 /* 1 Smart Card required */ +#define WBC_ACB_TRUSTED_FOR_DELEGATION 0x00002000 /* 1 Trusted for Delegation */ +#define WBC_ACB_NOT_DELEGATED 0x00004000 /* 1 Not delegated */ +#define WBC_ACB_USE_DES_KEY_ONLY 0x00008000 /* 1 Use DES key only */ +#define WBC_ACB_DONT_REQUIRE_PREAUTH 0x00010000 /* 1 Preauth not required */ +#define WBC_ACB_PW_EXPIRED 0x00020000 /* 1 Password Expired */ +#define WBC_ACB_NO_AUTH_DATA_REQD 0x00080000 /* 1 = No authorization data required */ + +struct wbcAuthErrorInfo { + uint32_t nt_status; + char *nt_string; + int32_t pam_error; + char *display_string; +}; + +/** + * @brief User Password Policy Information + **/ + +/* wbcUserPasswordPolicyInfo->password_properties */ + +#define WBC_DOMAIN_PASSWORD_COMPLEX 0x00000001 +#define WBC_DOMAIN_PASSWORD_NO_ANON_CHANGE 0x00000002 +#define WBC_DOMAIN_PASSWORD_NO_CLEAR_CHANGE 0x00000004 +#define WBC_DOMAIN_PASSWORD_LOCKOUT_ADMINS 0x00000008 +#define WBC_DOMAIN_PASSWORD_STORE_CLEARTEXT 0x00000010 +#define WBC_DOMAIN_REFUSE_PASSWORD_CHANGE 0x00000020 + +struct wbcUserPasswordPolicyInfo { + uint32_t min_length_password; + uint32_t password_history; + uint32_t password_properties; + uint64_t expire; + uint64_t min_passwordage; +}; + +/** + * @brief Change Password Reject Reason + **/ + +enum wbcPasswordChangeRejectReason { + WBC_PWD_CHANGE_REJECT_OTHER=0, + WBC_PWD_CHANGE_REJECT_TOO_SHORT=1, + WBC_PWD_CHANGE_REJECT_IN_HISTORY=2, + WBC_PWD_CHANGE_REJECT_COMPLEXITY=5 +}; + +/** + * @brief Logoff User Parameters + **/ + +struct wbcLogoffUserParams { + const char *username; + size_t num_blobs; + struct wbcNamedBlob *blobs; +}; + +/** @brief Credential cache log-on parameters + * + */ + +struct wbcCredentialCacheParams { + const char *account_name; + const char *domain_name; + enum wbcCredentialCacheLevel { + WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP = 1 + } level; + size_t num_blobs; + struct wbcNamedBlob *blobs; +}; + + +/** @brief Info returned by credential cache auth + * + */ + +struct wbcCredentialCacheInfo { + size_t num_blobs; + struct wbcNamedBlob *blobs; +}; + +/* + * DomainControllerInfo struct + */ +struct wbcDomainControllerInfo { + char *dc_name; +}; + +/* + * DomainControllerInfoEx struct + */ +struct wbcDomainControllerInfoEx { + const char *dc_unc; + const char *dc_address; + uint16_t dc_address_type; + struct wbcGuid *domain_guid; + const char *domain_name; + const char *forest_name; + uint32_t dc_flags; + const char *dc_site_name; + const char *client_site_name; +}; + +/********************************************************** + * Memory Management + **********************************************************/ + +/** + * @brief Free library allocated memory + * + * @param *p Pointer to free + * + * @return void + **/ +void wbcFreeMemory(void*); + + +/* + * Utility functions for dealing with SIDs + */ + +/** + * @brief Convert a binary SID to a character string + * + * @param sid Binary Security Identifier + * @param **sid_string Resulting character string + * + * @return #wbcErr + **/ +wbcErr wbcSidToString(const struct wbcDomainSid *sid, + char **sid_string); + +/** + * @brief Convert a character string to a binary SID + * + * @param *str Character string in the form of S-... + * @param sid Resulting binary SID + * + * @return #wbcErr + **/ +wbcErr wbcStringToSid(const char *sid_string, + struct wbcDomainSid *sid); + +/* + * Utility functions for dealing with GUIDs + */ + +/** + * @brief Convert a binary GUID to a character string + * + * @param guid Binary Guid + * @param **guid_string Resulting character string + * + * @return #wbcErr + **/ +wbcErr wbcGuidToString(const struct wbcGuid *guid, + char **guid_string); + +/** + * @brief Convert a character string to a binary GUID + * + * @param *str Character string + * @param guid Resulting binary GUID + * + * @return #wbcErr + **/ +wbcErr wbcStringToGuid(const char *guid_string, + struct wbcGuid *guid); + +/** + * @brief Ping winbindd to see if the daemon is running + * + * @return #wbcErr + **/ +wbcErr wbcPing(void); + +wbcErr wbcLibraryDetails(struct wbcLibraryDetails **details); + +wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **details); + +/********************************************************** + * Name/SID conversion + **********************************************************/ + +/** + * @brief Convert a domain and name to SID + * + * @param domain Domain name (possibly "") + * @param name User or group name + * @param *sid Pointer to the resolved domain SID + * @param *name_type Pointer to the SID type + * + * @return #wbcErr + **/ +wbcErr wbcLookupName(const char *dom_name, + const char *name, + struct wbcDomainSid *sid, + enum wbcSidType *name_type); + +/** + * @brief Convert a SID to a domain and name + * + * @param *sid Pointer to the domain SID to be resolved + * @param pdomain Resolved Domain name (possibly "") + * @param pname Resolved User or group name + * @param *pname_type Pointer to the resolved SID type + * + * @return #wbcErr + **/ +wbcErr wbcLookupSid(const struct wbcDomainSid *sid, + char **domain, + char **name, + enum wbcSidType *name_type); + +/** + * @brief Translate a collection of RIDs within a domain to names + */ +wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid, + int num_rids, + uint32_t *rids, + const char **domain_name, + const char ***names, + enum wbcSidType **types); + +/* + * @brief Get the groups a user belongs to + **/ +wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid, + bool domain_groups_only, + uint32_t *num_sids, + struct wbcDomainSid **sids); + +/** + * @brief Lists Users + **/ +wbcErr wbcListUsers(const char *domain_name, + uint32_t *num_users, + const char ***users); + +/** + * @brief Lists Groups + **/ +wbcErr wbcListGroups(const char *domain_name, + uint32_t *num_groups, + const char ***groups); + +wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid, + char **pdomain, + char **pfullname, + enum wbcSidType *pname_type); + +/********************************************************** + * SID/uid/gid Mappings + **********************************************************/ + +/** + * @brief Convert a Windows SID to a Unix uid, allocating an uid if needed + * + * @param *sid Pointer to the domain SID to be resolved + * @param *puid Pointer to the resolved uid_t value + * + * @return #wbcErr + * + **/ +wbcErr wbcSidToUid(const struct wbcDomainSid *sid, + uid_t *puid); + +/** + * @brief Convert a Windows SID to a Unix uid if there already is a mapping + * + * @param *sid Pointer to the domain SID to be resolved + * @param *puid Pointer to the resolved uid_t value + * + * @return #wbcErr + * + **/ +wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid, + uid_t *puid); + +/** + * @brief Convert a Unix uid to a Windows SID, allocating a SID if needed + * + * @param uid Unix uid to be resolved + * @param *sid Pointer to the resolved domain SID + * + * @return #wbcErr + * + **/ +wbcErr wbcUidToSid(uid_t uid, + struct wbcDomainSid *sid); + +/** + * @brief Convert a Unix uid to a Windows SID if there already is a mapping + * + * @param uid Unix uid to be resolved + * @param *sid Pointer to the resolved domain SID + * + * @return #wbcErr + * + **/ +wbcErr wbcQueryUidToSid(uid_t uid, + struct wbcDomainSid *sid); + +/** + * @brief Convert a Windows SID to a Unix gid, allocating a gid if needed + * + * @param *sid Pointer to the domain SID to be resolved + * @param *pgid Pointer to the resolved gid_t value + * + * @return #wbcErr + * + **/ +wbcErr wbcSidToGid(const struct wbcDomainSid *sid, + gid_t *pgid); + +/** + * @brief Convert a Windows SID to a Unix gid if there already is a mapping + * + * @param *sid Pointer to the domain SID to be resolved + * @param *pgid Pointer to the resolved gid_t value + * + * @return #wbcErr + * + **/ +wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid, + gid_t *pgid); + +/** + * @brief Convert a Unix gid to a Windows SID, allocating a SID if needed + * + * @param gid Unix gid to be resolved + * @param *sid Pointer to the resolved domain SID + * + * @return #wbcErr + * + **/ +wbcErr wbcGidToSid(gid_t gid, + struct wbcDomainSid *sid); + +/** + * @brief Convert a Unix gid to a Windows SID if there already is a mapping + * + * @param gid Unix gid to be resolved + * @param *sid Pointer to the resolved domain SID + * + * @return #wbcErr + * + **/ +wbcErr wbcQueryGidToSid(gid_t gid, + struct wbcDomainSid *sid); + +/** + * @brief Obtain a new uid from Winbind + * + * @param *puid *pointer to the allocated uid + * + * @return #wbcErr + **/ +wbcErr wbcAllocateUid(uid_t *puid); + +/** + * @brief Obtain a new gid from Winbind + * + * @param *pgid Pointer to the allocated gid + * + * @return #wbcErr + **/ +wbcErr wbcAllocateGid(gid_t *pgid); + +/** + * @brief Set an user id mapping + * + * @param uid Uid of the desired mapping. + * @param *sid Pointer to the sid of the diresired mapping. + * + * @return #wbcErr + **/ +wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid); + +/** + * @brief Set a group id mapping + * + * @param gid Gid of the desired mapping. + * @param *sid Pointer to the sid of the diresired mapping. + * + * @return #wbcErr + **/ +wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid); + +/** + * @brief Remove a user id mapping + * + * @param uid Uid of the mapping to remove. + * @param *sid Pointer to the sid of the mapping to remove. + * + * @return #wbcErr + **/ +wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid); + +/** + * @brief Remove a group id mapping + * + * @param gid Gid of the mapping to remove. + * @param *sid Pointer to the sid of the mapping to remove. + * + * @return #wbcErr + **/ +wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid); + +/** + * @brief Set the highwater mark for allocated uids. + * + * @param uid_hwm The new uid highwater mark value + * + * @return #wbcErr + **/ +wbcErr wbcSetUidHwm(uid_t uid_hwm); + +/** + * @brief Set the highwater mark for allocated gids. + * + * @param gid_hwm The new gid highwater mark value + * + * @return #wbcErr + **/ +wbcErr wbcSetGidHwm(gid_t gid_hwm); + +/********************************************************** + * NSS Lookup User/Group details + **********************************************************/ + +/** + * @brief Fill in a struct passwd* for a domain user based + * on username + * + * @param *name Username to lookup + * @param **pwd Pointer to resulting struct passwd* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetpwnam(const char *name, struct passwd **pwd); + +/** + * @brief Fill in a struct passwd* for a domain user based + * on uid + * + * @param uid Uid to lookup + * @param **pwd Pointer to resulting struct passwd* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd); + +/** + * @brief Fill in a struct passwd* for a domain user based + * on username + * + * @param *name Username to lookup + * @param **grp Pointer to resulting struct group* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetgrnam(const char *name, struct group **grp); + +/** + * @brief Fill in a struct passwd* for a domain user based + * on uid + * + * @param gid Uid to lookup + * @param **grp Pointer to resulting struct group* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetgrgid(gid_t gid, struct group **grp); + +/** + * @brief Reset the passwd iterator + * + * @return #wbcErr + **/ +wbcErr wbcSetpwent(void); + +/** + * @brief Close the passwd iterator + * + * @return #wbcErr + **/ +wbcErr wbcEndpwent(void); + +/** + * @brief Return the next struct passwd* entry from the pwent iterator + * + * @param **pwd Pointer to resulting struct passwd* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetpwent(struct passwd **pwd); + +/** + * @brief Reset the group iterator + * + * @return #wbcErr + **/ +wbcErr wbcSetgrent(void); + +/** + * @brief Close the group iterator + * + * @return #wbcErr + **/ +wbcErr wbcEndgrent(void); + +/** + * @brief Return the next struct group* entry from the pwent iterator + * + * @param **grp Pointer to resulting struct group* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetgrent(struct group **grp); + +/** + * @brief Return the next struct group* entry from the pwent iterator + * + * This is similar to #wbcGetgrent, just that the member list is empty + * + * @param **grp Pointer to resulting struct group* from the query. + * + * @return #wbcErr + **/ +wbcErr wbcGetgrlist(struct group **grp); + +/** + * @brief Return the unix group array belonging to the given user + * + * @param *account The given user name + * @param *num_groups Number of elements returned in the groups array + * @param **_groups Pointer to resulting gid_t array. + * + * @return #wbcErr + **/ +wbcErr wbcGetGroups(const char *account, + uint32_t *num_groups, + gid_t **_groups); + + +/********************************************************** + * Lookup Domain information + **********************************************************/ + +/** + * @brief Lookup the current status of a trusted domain + * + * @param domain Domain to query + * @param *dinfo Pointer to returned domain_info struct + * + * @return #wbcErr + **/ +wbcErr wbcDomainInfo(const char *domain, + struct wbcDomainInfo **info); + +/** + * @brief Enumerate the domain trusts known by Winbind + * + * @param **domains Pointer to the allocated domain list array + * @param *num_domains Pointer to number of domains returned + * + * @return #wbcErr + **/ +wbcErr wbcListTrusts(struct wbcDomainInfo **domains, + size_t *num_domains); + +/* Flags for wbcLookupDomainController */ + +#define WBC_LOOKUP_DC_FORCE_REDISCOVERY 0x00000001 +#define WBC_LOOKUP_DC_DS_REQUIRED 0x00000010 +#define WBC_LOOKUP_DC_DS_PREFERRED 0x00000020 +#define WBC_LOOKUP_DC_GC_SERVER_REQUIRED 0x00000040 +#define WBC_LOOKUP_DC_PDC_REQUIRED 0x00000080 +#define WBC_LOOKUP_DC_BACKGROUND_ONLY 0x00000100 +#define WBC_LOOKUP_DC_IP_REQUIRED 0x00000200 +#define WBC_LOOKUP_DC_KDC_REQUIRED 0x00000400 +#define WBC_LOOKUP_DC_TIMESERV_REQUIRED 0x00000800 +#define WBC_LOOKUP_DC_WRITABLE_REQUIRED 0x00001000 +#define WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED 0x00002000 +#define WBC_LOOKUP_DC_AVOID_SELF 0x00004000 +#define WBC_LOOKUP_DC_ONLY_LDAP_NEEDED 0x00008000 +#define WBC_LOOKUP_DC_IS_FLAT_NAME 0x00010000 +#define WBC_LOOKUP_DC_IS_DNS_NAME 0x00020000 +#define WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE 0x00040000 +#define WBC_LOOKUP_DC_DS_6_REQUIRED 0x00080000 +#define WBC_LOOKUP_DC_RETURN_DNS_NAME 0x40000000 +#define WBC_LOOKUP_DC_RETURN_FLAT_NAME 0x80000000 + +/** + * @brief Enumerate the domain trusts known by Winbind + * + * @param domain Name of the domain to query for a DC + * @param flags Bit flags used to control the domain location query + * @param *dc_info Pointer to the returned domain controller information + * + * @return #wbcErr + **/ +wbcErr wbcLookupDomainController(const char *domain, + uint32_t flags, + struct wbcDomainControllerInfo **dc_info); + +/** + * @brief Get extended domain controller information + * + * @param domain Name of the domain to query for a DC + * @param guid Guid of the domain to query for a DC + * @param site Site of the domain to query for a DC + * @param flags Bit flags used to control the domain location query + * @param *dc_info Pointer to the returned extended domain controller information + * + * @return #wbcErr + **/ +wbcErr wbcLookupDomainControllerEx(const char *domain, + struct wbcGuid *guid, + const char *site, + uint32_t flags, + struct wbcDomainControllerInfoEx **dc_info); + +/********************************************************** + * Athenticate functions + **********************************************************/ + +/** + * @brief Authenticate a username/password pair + * + * @param username Name of user to authenticate + * @param password Clear text password os user + * + * @return #wbcErr + **/ +wbcErr wbcAuthenticateUser(const char *username, + const char *password); + +/** + * @brief Authenticate with more detailed information + * + * @param params Input parameters, WBC_AUTH_USER_LEVEL_HASH + * is not supported yet + * @param info Output details on WBC_ERR_SUCCESS + * @param error Output details on WBC_ERR_AUTH_ERROR + * + * @return #wbcErr + **/ +wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params, + struct wbcAuthUserInfo **info, + struct wbcAuthErrorInfo **error); + +/** + * @brief Logon a User + * + * @param[in] params Pointer to a wbcLogonUserParams structure + * @param[out] info Pointer to a pointer to a wbcLogonUserInfo structure + * @param[out] error Pointer to a pointer to a wbcAuthErrorInfo structure + * @param[out] policy Pointer to a pointer to a wbcUserPasswordPolicyInfo structure + * + * @return #wbcErr + **/ +wbcErr wbcLogonUser(const struct wbcLogonUserParams *params, + struct wbcLogonUserInfo **info, + struct wbcAuthErrorInfo **error, + struct wbcUserPasswordPolicyInfo **policy); + +/** + * @brief Trigger a logoff notification to Winbind for a specific user + * + * @param username Name of user to remove from Winbind's list of + * logged on users. + * @param uid Uid assigned to the username + * @param ccfilename Absolute path to the Krb5 credentials cache to + * be removed + * + * @return #wbcErr + **/ +wbcErr wbcLogoffUser(const char *username, + uid_t uid, + const char *ccfilename); + +/** + * @brief Trigger an extended logoff notification to Winbind for a specific user + * + * @param params A wbcLogoffUserParams structure + * @param error User output details on error + * + * @return #wbcErr + **/ +wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params, + struct wbcAuthErrorInfo **error); + +/** + * @brief Change a password for a user + * + * @param username Name of user to authenticate + * @param old_password Old clear text password of user + * @param new_password New clear text password of user + * + * @return #wbcErr + **/ +wbcErr wbcChangeUserPassword(const char *username, + const char *old_password, + const char *new_password); + +/** + * @brief Change a password for a user with more detailed information upon + * failure + * + * @param params Input parameters + * @param error User output details on WBC_ERR_PWD_CHANGE_FAILED + * @param reject_reason New password reject reason on WBC_ERR_PWD_CHANGE_FAILED + * @param policy Password policy output details on WBC_ERR_PWD_CHANGE_FAILED + * + * @return #wbcErr + **/ +wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params, + struct wbcAuthErrorInfo **error, + enum wbcPasswordChangeRejectReason *reject_reason, + struct wbcUserPasswordPolicyInfo **policy); + +/** + * @brief Authenticate a user with cached credentials + * + * @param *params Pointer to a wbcCredentialCacheParams structure + * @param **info Pointer to a pointer to a wbcCredentialCacheInfo structure + * @param **error Pointer to a pointer to a wbcAuthErrorInfo structure + * + * @return #wbcErr + **/ +wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params, + struct wbcCredentialCacheInfo **info, + struct wbcAuthErrorInfo **error); + +/********************************************************** + * Resolve functions + **********************************************************/ + +/** + * @brief Resolve a NetbiosName via WINS + * + * @param name Name to resolve + * @param *ip Pointer to the ip address string + * + * @return #wbcErr + **/ +wbcErr wbcResolveWinsByName(const char *name, char **ip); + +/** + * @brief Resolve an IP address via WINS into a NetbiosName + * + * @param ip The ip address string + * @param *name Pointer to the name + * + * @return #wbcErr + * + **/ +wbcErr wbcResolveWinsByIP(const char *ip, char **name); + +/********************************************************** + * Trusted domain functions + **********************************************************/ + +/** + * @brief Trigger a verification of the trust credentials of a specific domain + * + * @param *domain The name of the domain, only NULL for the default domain is + * supported yet. Other values than NULL will result in + * WBC_ERR_NOT_IMPLEMENTED. + * @param error Output details on WBC_ERR_AUTH_ERROR + * + * @return #wbcErr + **/ +wbcErr wbcCheckTrustCredentials(const char *domain, + struct wbcAuthErrorInfo **error); + +/********************************************************** + * Helper functions + **********************************************************/ + +/** + * @brief Initialize a named blob and add to list of blobs + * + * @param[in,out] num_blobs Pointer to the number of blobs + * @param[in,out] blobs Pointer to an array of blobs + * @param[in] name Name of the new named blob + * @param[in] flags Flags of the new named blob + * @param[in] data Blob data of new blob + * @param[in] length Blob data length of new blob + * + * @return #wbcErr + **/ +wbcErr wbcAddNamedBlob(size_t *num_blobs, + struct wbcNamedBlob **blobs, + const char *name, + uint32_t flags, + uint8_t *data, + size_t length); + +#endif /* _WBCLIENT_H */ diff --git a/nsswitch/libwbclient/wbclient_internal.h b/nsswitch/libwbclient/wbclient_internal.h new file mode 100644 index 0000000000..fc03c5409b --- /dev/null +++ b/nsswitch/libwbclient/wbclient_internal.h @@ -0,0 +1,32 @@ +/* + Unix SMB/CIFS implementation. + + Winbind client API + + Copyright (C) Gerald (Jerry) Carter 2007 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WBCLIENT_INTERNAL_H +#define _WBCLIENT_INTERNAL_H + +/* Private functions */ + +wbcErr wbcRequestResponse(int cmd, + struct winbindd_request *request, + struct winbindd_response *response); + + +#endif /* _WBCLIENT_INTERNAL_H */ diff --git a/nsswitch/pam_winbind.c b/nsswitch/pam_winbind.c new file mode 100644 index 0000000000..d049bdb1e7 --- /dev/null +++ b/nsswitch/pam_winbind.c @@ -0,0 +1,3204 @@ +/* pam_winbind module + + Copyright Andrew Tridgell 2000 + Copyright Tim Potter 2000 + Copyright Andrew Bartlett 2002 + Copyright Guenther Deschner 2005-2008 + + largely based on pam_userdb by Cristian Gafton also + contains large slabs of code from pam_unix by Elliot Lee + (see copyright below for full details) +*/ + +#include "pam_winbind.h" + +static int wbc_error_to_pam_error(wbcErr status) +{ + switch (status) { + case WBC_ERR_SUCCESS: + return PAM_SUCCESS; + case WBC_ERR_NOT_IMPLEMENTED: + return PAM_SERVICE_ERR; + case WBC_ERR_UNKNOWN_FAILURE: + break; + case WBC_ERR_NO_MEMORY: + return PAM_BUF_ERR; + case WBC_ERR_INVALID_SID: + case WBC_ERR_INVALID_PARAM: + break; + case WBC_ERR_WINBIND_NOT_AVAILABLE: + return PAM_AUTHINFO_UNAVAIL; + case WBC_ERR_DOMAIN_NOT_FOUND: + return PAM_AUTHINFO_UNAVAIL; + case WBC_ERR_INVALID_RESPONSE: + return PAM_BUF_ERR; + case WBC_ERR_NSS_ERROR: + return PAM_USER_UNKNOWN; + case WBC_ERR_AUTH_ERROR: + return PAM_AUTH_ERR; + case WBC_ERR_UNKNOWN_USER: + return PAM_USER_UNKNOWN; + case WBC_ERR_UNKNOWN_GROUP: + return PAM_USER_UNKNOWN; + case WBC_ERR_PWD_CHANGE_FAILED: + break; + } + + /* be paranoid */ + return PAM_AUTH_ERR; +} + +static const char *_pam_error_code_str(int err) +{ + switch (err) { + case PAM_SUCCESS: + return "PAM_SUCCESS"; + case PAM_OPEN_ERR: + return "PAM_OPEN_ERR"; + case PAM_SYMBOL_ERR: + return "PAM_SYMBOL_ERR"; + case PAM_SERVICE_ERR: + return "PAM_SERVICE_ERR"; + case PAM_SYSTEM_ERR: + return "PAM_SYSTEM_ERR"; + case PAM_BUF_ERR: + return "PAM_BUF_ERR"; + case PAM_PERM_DENIED: + return "PAM_PERM_DENIED"; + case PAM_AUTH_ERR: + return "PAM_AUTH_ERR"; + case PAM_CRED_INSUFFICIENT: + return "PAM_CRED_INSUFFICIENT"; + case PAM_AUTHINFO_UNAVAIL: + return "PAM_AUTHINFO_UNAVAIL"; + case PAM_USER_UNKNOWN: + return "PAM_USER_UNKNOWN"; + case PAM_MAXTRIES: + return "PAM_MAXTRIES"; + case PAM_NEW_AUTHTOK_REQD: + return "PAM_NEW_AUTHTOK_REQD"; + case PAM_ACCT_EXPIRED: + return "PAM_ACCT_EXPIRED"; + case PAM_SESSION_ERR: + return "PAM_SESSION_ERR"; + case PAM_CRED_UNAVAIL: + return "PAM_CRED_UNAVAIL"; + case PAM_CRED_EXPIRED: + return "PAM_CRED_EXPIRED"; + case PAM_CRED_ERR: + return "PAM_CRED_ERR"; + case PAM_NO_MODULE_DATA: + return "PAM_NO_MODULE_DATA"; + case PAM_CONV_ERR: + return "PAM_CONV_ERR"; + case PAM_AUTHTOK_ERR: + return "PAM_AUTHTOK_ERR"; + case PAM_AUTHTOK_RECOVER_ERR: + return "PAM_AUTHTOK_RECOVER_ERR"; + case PAM_AUTHTOK_LOCK_BUSY: + return "PAM_AUTHTOK_LOCK_BUSY"; + case PAM_AUTHTOK_DISABLE_AGING: + return "PAM_AUTHTOK_DISABLE_AGING"; + case PAM_TRY_AGAIN: + return "PAM_TRY_AGAIN"; + case PAM_IGNORE: + return "PAM_IGNORE"; + case PAM_ABORT: + return "PAM_ABORT"; + case PAM_AUTHTOK_EXPIRED: + return "PAM_AUTHTOK_EXPIRED"; +#ifdef PAM_MODULE_UNKNOWN + case PAM_MODULE_UNKNOWN: + return "PAM_MODULE_UNKNOWN"; +#endif +#ifdef PAM_BAD_ITEM + case PAM_BAD_ITEM: + return "PAM_BAD_ITEM"; +#endif +#ifdef PAM_CONV_AGAIN + case PAM_CONV_AGAIN: + return "PAM_CONV_AGAIN"; +#endif +#ifdef PAM_INCOMPLETE + case PAM_INCOMPLETE: + return "PAM_INCOMPLETE"; +#endif + default: + return NULL; + } +} + +#define _PAM_LOG_FUNCTION_ENTER(function, ctx) \ + do { \ + _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] ENTER: " \ + function " (flags: 0x%04x)", ctx->pamh, ctx->flags); \ + _pam_log_state(ctx); \ + } while (0) + +#define _PAM_LOG_FUNCTION_LEAVE(function, ctx, retval) \ + do { \ + _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] LEAVE: " \ + function " returning %d (%s)", ctx->pamh, retval, \ + _pam_error_code_str(retval)); \ + _pam_log_state(ctx); \ + } while (0) + +/* data tokens */ + +#define MAX_PASSWD_TRIES 3 + +#ifdef HAVE_GETTEXT +static char initialized = 0; + +static inline void textdomain_init(void); +static inline void textdomain_init(void) +{ + if (!initialized) { + bindtextdomain(MODULE_NAME, dyn_LOCALEDIR); + initialized = 1; + } + return; +} +#endif + + +/* + * Work around the pam API that has functions with void ** as parameters + * These lead to strict aliasing warnings with gcc. + */ +static int _pam_get_item(const pam_handle_t *pamh, + int item_type, + const void *_item) +{ + const void **item = (const void **)_item; + return pam_get_item(pamh, item_type, item); +} +static int _pam_get_data(const pam_handle_t *pamh, + const char *module_data_name, + const void *_data) +{ + const void **data = (const void **)_data; + return pam_get_data(pamh, module_data_name, data); +} + +/* some syslogging */ + +#ifdef HAVE_PAM_VSYSLOG +static void _pam_log_int(const pam_handle_t *pamh, + int err, + const char *format, + va_list args) +{ + pam_vsyslog(pamh, err, format, args); +} +#else +static void _pam_log_int(const pam_handle_t *pamh, + int err, + const char *format, + va_list args) +{ + char *format2 = NULL; + const char *service; + + _pam_get_item(pamh, PAM_SERVICE, &service); + + format2 = (char *)malloc(strlen(MODULE_NAME)+strlen(format)+strlen(service)+5); + if (format2 == NULL) { + /* what else todo ? */ + vsyslog(err, format, args); + return; + } + + sprintf(format2, "%s(%s): %s", MODULE_NAME, service, format); + vsyslog(err, format2, args); + SAFE_FREE(format2); +} +#endif /* HAVE_PAM_VSYSLOG */ + +static bool _pam_log_is_silent(int ctrl) +{ + return on(ctrl, WINBIND_SILENT); +} + +static void _pam_log(struct pwb_context *r, int err, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void _pam_log(struct pwb_context *r, int err, const char *format, ...) +{ + va_list args; + + if (_pam_log_is_silent(r->ctrl)) { + return; + } + + va_start(args, format); + _pam_log_int(r->pamh, err, format, args); + va_end(args); +} +static void __pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); +static void __pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) +{ + va_list args; + + if (_pam_log_is_silent(ctrl)) { + return; + } + + va_start(args, format); + _pam_log_int(pamh, err, format, args); + va_end(args); +} + +static bool _pam_log_is_debug_enabled(int ctrl) +{ + if (ctrl == -1) { + return false; + } + + if (_pam_log_is_silent(ctrl)) { + return false; + } + + if (!(ctrl & WINBIND_DEBUG_ARG)) { + return false; + } + + return true; +} + +static bool _pam_log_is_debug_state_enabled(int ctrl) +{ + if (!(ctrl & WINBIND_DEBUG_STATE)) { + return false; + } + + return _pam_log_is_debug_enabled(ctrl); +} + +static void _pam_log_debug(struct pwb_context *r, int err, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void _pam_log_debug(struct pwb_context *r, int err, const char *format, ...) +{ + va_list args; + + if (!_pam_log_is_debug_enabled(r->ctrl)) { + return; + } + + va_start(args, format); + _pam_log_int(r->pamh, err, format, args); + va_end(args); +} +static void __pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); +static void __pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) +{ + va_list args; + + if (!_pam_log_is_debug_enabled(ctrl)) { + return; + } + + va_start(args, format); + _pam_log_int(pamh, err, format, args); + va_end(args); +} + +static void _pam_log_state_datum(struct pwb_context *ctx, + int item_type, + const char *key, + int is_string) +{ + const void *data = NULL; + if (item_type != 0) { + pam_get_item(ctx->pamh, item_type, &data); + } else { + pam_get_data(ctx->pamh, key, &data); + } + if (data != NULL) { + const char *type = (item_type != 0) ? "ITEM" : "DATA"; + if (is_string != 0) { + _pam_log_debug(ctx, LOG_DEBUG, + "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", + ctx->pamh, type, key, (const char *)data, + data); + } else { + _pam_log_debug(ctx, LOG_DEBUG, + "[pamh: %p] STATE: %s(%s) = %p", + ctx->pamh, type, key, data); + } + } +} + +#define _PAM_LOG_STATE_DATA_POINTER(ctx, module_data_name) \ + _pam_log_state_datum(ctx, 0, module_data_name, 0) + +#define _PAM_LOG_STATE_DATA_STRING(ctx, module_data_name) \ + _pam_log_state_datum(ctx, 0, module_data_name, 1) + +#define _PAM_LOG_STATE_ITEM_POINTER(ctx, item_type) \ + _pam_log_state_datum(ctx, item_type, #item_type, 0) + +#define _PAM_LOG_STATE_ITEM_STRING(ctx, item_type) \ + _pam_log_state_datum(ctx, item_type, #item_type, 1) + +#ifdef DEBUG_PASSWORD +#define _LOG_PASSWORD_AS_STRING 1 +#else +#define _LOG_PASSWORD_AS_STRING 0 +#endif + +#define _PAM_LOG_STATE_ITEM_PASSWORD(ctx, item_type) \ + _pam_log_state_datum(ctx, item_type, #item_type, \ + _LOG_PASSWORD_AS_STRING) + +static void _pam_log_state(struct pwb_context *ctx) +{ + if (!_pam_log_is_debug_state_enabled(ctx->ctrl)) { + return; + } + + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_SERVICE); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_USER); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_TTY); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_RHOST); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_RUSER); + _PAM_LOG_STATE_ITEM_PASSWORD(ctx, PAM_OLDAUTHTOK); + _PAM_LOG_STATE_ITEM_PASSWORD(ctx, PAM_AUTHTOK); + _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_USER_PROMPT); + _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_CONV); +#ifdef PAM_FAIL_DELAY + _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_FAIL_DELAY); +#endif +#ifdef PAM_REPOSITORY + _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_REPOSITORY); +#endif + + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_HOMEDIR); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_LOGONSCRIPT); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_LOGONSERVER); + _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_PROFILEPATH); + _PAM_LOG_STATE_DATA_STRING(ctx, + PAM_WINBIND_NEW_AUTHTOK_REQD); + /* Use atoi to get PAM result code */ + _PAM_LOG_STATE_DATA_STRING(ctx, + PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); + _PAM_LOG_STATE_DATA_POINTER(ctx, PAM_WINBIND_PWD_LAST_SET); +} + +static int _pam_parse(const pam_handle_t *pamh, + int flags, + int argc, + const char **argv, + dictionary **result_d) +{ + int ctrl = 0; + const char *config_file = NULL; + int i; + const char **v; + dictionary *d = NULL; + + if (flags & PAM_SILENT) { + ctrl |= WINBIND_SILENT; + } + + for (i=argc,v=argv; i-- > 0; ++v) { + if (!strncasecmp(*v, "config", strlen("config"))) { + ctrl |= WINBIND_CONFIG_FILE; + config_file = v[i]; + break; + } + } + + if (config_file == NULL) { + config_file = PAM_WINBIND_CONFIG_FILE; + } + + d = iniparser_load(config_file); + if (d == NULL) { + goto config_from_pam; + } + + if (iniparser_getboolean(d, "global:debug", false)) { + ctrl |= WINBIND_DEBUG_ARG; + } + + if (iniparser_getboolean(d, "global:debug_state", false)) { + ctrl |= WINBIND_DEBUG_STATE; + } + + if (iniparser_getboolean(d, "global:cached_login", false)) { + ctrl |= WINBIND_CACHED_LOGIN; + } + + if (iniparser_getboolean(d, "global:krb5_auth", false)) { + ctrl |= WINBIND_KRB5_AUTH; + } + + if (iniparser_getboolean(d, "global:silent", false)) { + ctrl |= WINBIND_SILENT; + } + + if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) { + ctrl |= WINBIND_KRB5_CCACHE_TYPE; + } + + if ((iniparser_getstr(d, "global:require-membership-of") != NULL) || + (iniparser_getstr(d, "global:require_membership_of") != NULL)) { + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + } + + if (iniparser_getboolean(d, "global:try_first_pass", false)) { + ctrl |= WINBIND_TRY_FIRST_PASS_ARG; + } + + if (iniparser_getint(d, "global:warn_pwd_expire", 0)) { + ctrl |= WINBIND_WARN_PWD_EXPIRE; + } + + if (iniparser_getboolean(d, "global:mkhomedir", false)) { + ctrl |= WINBIND_MKHOMEDIR; + } + +config_from_pam: + /* step through arguments */ + for (i=argc,v=argv; i-- > 0; ++v) { + + /* generic options */ + if (!strcmp(*v,"debug")) + ctrl |= WINBIND_DEBUG_ARG; + else if (!strcasecmp(*v, "debug_state")) + ctrl |= WINBIND_DEBUG_STATE; + else if (!strcasecmp(*v, "silent")) + ctrl |= WINBIND_SILENT; + else if (!strcasecmp(*v, "use_authtok")) + ctrl |= WINBIND_USE_AUTHTOK_ARG; + else if (!strcasecmp(*v, "use_first_pass")) + ctrl |= WINBIND_USE_FIRST_PASS_ARG; + else if (!strcasecmp(*v, "try_first_pass")) + ctrl |= WINBIND_TRY_FIRST_PASS_ARG; + else if (!strcasecmp(*v, "unknown_ok")) + ctrl |= WINBIND_UNKNOWN_OK_ARG; + else if (!strncasecmp(*v, "require_membership_of", + strlen("require_membership_of"))) + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + else if (!strncasecmp(*v, "require-membership-of", + strlen("require-membership-of"))) + ctrl |= WINBIND_REQUIRED_MEMBERSHIP; + else if (!strcasecmp(*v, "krb5_auth")) + ctrl |= WINBIND_KRB5_AUTH; + else if (!strncasecmp(*v, "krb5_ccache_type", + strlen("krb5_ccache_type"))) + ctrl |= WINBIND_KRB5_CCACHE_TYPE; + else if (!strcasecmp(*v, "cached_login")) + ctrl |= WINBIND_CACHED_LOGIN; + else if (!strcasecmp(*v, "mkhomedir")) + ctrl |= WINBIND_MKHOMEDIR; + else { + __pam_log(pamh, ctrl, LOG_ERR, + "pam_parse: unknown option: %s", *v); + return -1; + } + + } + + if (result_d) { + *result_d = d; + } else { + if (d) { + iniparser_freedict(d); + } + } + + return ctrl; +}; + +static int _pam_winbind_free_context(struct pwb_context *ctx) +{ + if (!ctx) { + return 0; + } + + if (ctx->dict) { + iniparser_freedict(ctx->dict); + } + + return 0; +} + +static int _pam_winbind_init_context(pam_handle_t *pamh, + int flags, + int argc, + const char **argv, + struct pwb_context **ctx_p) +{ + struct pwb_context *r = NULL; + +#ifdef HAVE_GETTEXT + textdomain_init(); +#endif + + r = TALLOC_ZERO_P(NULL, struct pwb_context); + if (!r) { + return PAM_BUF_ERR; + } + + talloc_set_destructor(r, _pam_winbind_free_context); + + r->pamh = pamh; + r->flags = flags; + r->argc = argc; + r->argv = argv; + r->ctrl = _pam_parse(pamh, flags, argc, argv, &r->dict); + if (r->ctrl == -1) { + TALLOC_FREE(r); + return PAM_SYSTEM_ERR; + } + + *ctx_p = r; + + return PAM_SUCCESS; +} + +static void _pam_winbind_cleanup_func(pam_handle_t *pamh, + void *data, + int error_status) +{ + int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); + if (_pam_log_is_debug_state_enabled(ctrl)) { + __pam_log_debug(pamh, ctrl, LOG_DEBUG, + "[pamh: %p] CLEAN: cleaning up PAM data %p " + "(error_status = %d)", pamh, data, + error_status); + } + TALLOC_FREE(data); +} + + +static const struct ntstatus_errors { + const char *ntstatus_string; + const char *error_string; +} ntstatus_errors[] = { + {"NT_STATUS_OK", + N_("Success")}, + {"NT_STATUS_BACKUP_CONTROLLER", + N_("No primary Domain Controler available")}, + {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + N_("No domain controllers found")}, + {"NT_STATUS_NO_LOGON_SERVERS", + N_("No logon servers")}, + {"NT_STATUS_PWD_TOO_SHORT", + N_("Password too short")}, + {"NT_STATUS_PWD_TOO_RECENT", + N_("The password of this user is too recent to change")}, + {"NT_STATUS_PWD_HISTORY_CONFLICT", + N_("Password is already in password history")}, + {"NT_STATUS_PASSWORD_EXPIRED", + N_("Your password has expired")}, + {"NT_STATUS_PASSWORD_MUST_CHANGE", + N_("You need to change your password now")}, + {"NT_STATUS_INVALID_WORKSTATION", + N_("You are not allowed to logon from this workstation")}, + {"NT_STATUS_INVALID_LOGON_HOURS", + N_("You are not allowed to logon at this time")}, + {"NT_STATUS_ACCOUNT_EXPIRED", + N_("Your account has expired. " + "Please contact your System administrator")}, /* SCNR */ + {"NT_STATUS_ACCOUNT_DISABLED", + N_("Your account is disabled. " + "Please contact your System administrator")}, /* SCNR */ + {"NT_STATUS_ACCOUNT_LOCKED_OUT", + N_("Your account has been locked. " + "Please contact your System administrator")}, /* SCNR */ + {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", + N_("Invalid Trust Account")}, + {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", + N_("Invalid Trust Account")}, + {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", + N_("Invalid Trust Account")}, + {"NT_STATUS_ACCESS_DENIED", + N_("Access is denied")}, + {NULL, NULL} +}; + +static const char *_get_ntstatus_error_string(const char *nt_status_string) +{ + int i; + for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { + if (!strcasecmp(ntstatus_errors[i].ntstatus_string, + nt_status_string)) { + return _(ntstatus_errors[i].error_string); + } + } + return NULL; +} + +/* --- authentication management functions --- */ + +/* Attempt a conversation */ + +static int converse(const pam_handle_t *pamh, + int nargs, + struct pam_message **message, + struct pam_response **response) +{ + int retval; + struct pam_conv *conv; + + retval = _pam_get_item(pamh, PAM_CONV, &conv); + if (retval == PAM_SUCCESS) { + retval = conv->conv(nargs, + (const struct pam_message **)message, + response, conv->appdata_ptr); + } + + return retval; /* propagate error status */ +} + + +static int _make_remark(struct pwb_context *ctx, + int type, + const char *text) +{ + int retval = PAM_SUCCESS; + + struct pam_message *pmsg[1], msg[1]; + struct pam_response *resp; + + if (ctx->flags & WINBIND_SILENT) { + return PAM_SUCCESS; + } + + pmsg[0] = &msg[0]; + msg[0].msg = discard_const_p(char, text); + msg[0].msg_style = type; + + resp = NULL; + retval = converse(ctx->pamh, 1, pmsg, &resp); + + if (resp) { + _pam_drop_reply(resp, 1); + } + return retval; +} + +static int _make_remark_v(struct pwb_context *ctx, + int type, + const char *format, + va_list args) +{ + char *var; + int ret; + + ret = vasprintf(&var, format, args); + if (ret < 0) { + _pam_log(ctx, LOG_ERR, "memory allocation failure"); + return ret; + } + + ret = _make_remark(ctx, type, var); + SAFE_FREE(var); + return ret; +} + +static int _make_remark_format(struct pwb_context *ctx, int type, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static int _make_remark_format(struct pwb_context *ctx, int type, const char *format, ...) +{ + int ret; + va_list args; + + va_start(args, format); + ret = _make_remark_v(ctx, type, format, args); + va_end(args); + return ret; +} + +static int pam_winbind_request_log(struct pwb_context *ctx, + int retval, + const char *user, + const char *fn) +{ + switch (retval) { + case PAM_AUTH_ERR: + /* incorrect password */ + _pam_log(ctx, LOG_WARNING, "user '%s' denied access " + "(incorrect password or invalid membership)", user); + return retval; + case PAM_ACCT_EXPIRED: + /* account expired */ + _pam_log(ctx, LOG_WARNING, "user '%s' account expired", + user); + return retval; + case PAM_AUTHTOK_EXPIRED: + /* password expired */ + _pam_log(ctx, LOG_WARNING, "user '%s' password expired", + user); + return retval; + case PAM_NEW_AUTHTOK_REQD: + /* new password required */ + _pam_log(ctx, LOG_WARNING, "user '%s' new password " + "required", user); + return retval; + case PAM_USER_UNKNOWN: + /* the user does not exist */ + _pam_log_debug(ctx, LOG_NOTICE, "user '%s' not found", + user); + if (ctx->ctrl & WINBIND_UNKNOWN_OK_ARG) { + return PAM_IGNORE; + } + return retval; + case PAM_SUCCESS: + /* Otherwise, the authentication looked good */ + if (strcmp(fn, "wbcLogonUser") == 0) { + _pam_log(ctx, LOG_NOTICE, + "user '%s' granted access", user); + } else { + _pam_log(ctx, LOG_NOTICE, + "user '%s' OK", user); + } + return retval; + default: + /* we don't know anything about this return value */ + _pam_log(ctx, LOG_ERR, + "internal module error (retval = %s(%d), user = '%s')", + _pam_error_code_str(retval), retval, user); + return retval; + } +} + +static int wbc_auth_error_to_pam_error(struct pwb_context *ctx, + struct wbcAuthErrorInfo *e, + wbcErr status, + const char *username, + const char *fn) +{ + int ret = PAM_AUTH_ERR; + + if (WBC_ERROR_IS_OK(status)) { + _pam_log_debug(ctx, LOG_DEBUG, "request %s succeeded", + fn); + ret = PAM_SUCCESS; + return pam_winbind_request_log(ctx, ret, username, fn); + } + + if (e) { + if (e->pam_error != PAM_SUCCESS) { + _pam_log(ctx, LOG_ERR, + "request %s failed: %s, " + "PAM error: %s (%d), NTSTATUS: %s, " + "Error message was: %s", + fn, + wbcErrorString(status), + _pam_error_code_str(e->pam_error), + e->pam_error, + e->nt_string, + e->display_string); + ret = e->pam_error; + return pam_winbind_request_log(ctx, ret, username, fn); + } + + _pam_log(ctx, LOG_ERR, "request %s failed, but PAM error 0!", fn); + + ret = PAM_SERVICE_ERR; + return pam_winbind_request_log(ctx, ret, username, fn); + } + + ret = wbc_error_to_pam_error(status); + return pam_winbind_request_log(ctx, ret, username, fn); +} + + +/** + * send a password expiry message if required + * + * @param ctx PAM winbind context. + * @param next_change expected (calculated) next expiry date. + * @param already_expired pointer to a boolean to indicate if the password is + * already expired. + * + * @return boolean Returns true if message has been sent, false if not. + */ + +static bool _pam_send_password_expiry_message(struct pwb_context *ctx, + time_t next_change, + time_t now, + int warn_pwd_expire, + bool *already_expired) +{ + int days = 0; + struct tm tm_now, tm_next_change; + + if (already_expired) { + *already_expired = false; + } + + if (next_change <= now) { + PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PASSWORD_EXPIRED"); + if (already_expired) { + *already_expired = true; + } + return true; + } + + if ((next_change < 0) || + (next_change > now + warn_pwd_expire * SECONDS_PER_DAY)) { + return false; + } + + if ((localtime_r(&now, &tm_now) == NULL) || + (localtime_r(&next_change, &tm_next_change) == NULL)) { + return false; + } + + days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - + (tm_now.tm_yday+tm_now.tm_year*365); + + if (days == 0) { + _make_remark(ctx, PAM_TEXT_INFO, + _("Your password expires today")); + return true; + } + + if (days > 0 && days < warn_pwd_expire) { + _make_remark_format(ctx, PAM_TEXT_INFO, + _("Your password will expire in %d %s"), + days, (days > 1) ? _("days"):_("day")); + return true; + } + + return false; +} + +/** + * Send a warning if the password expires in the near future + * + * @param ctx PAM winbind context. + * @param response The full authentication response structure. + * @param already_expired boolean, is the pwd already expired? + * + * @return void. + */ + +static void _pam_warn_password_expiry(struct pwb_context *ctx, + const struct wbcAuthUserInfo *info, + const struct wbcUserPasswordPolicyInfo *policy, + int warn_pwd_expire, + bool *already_expired) +{ + time_t now = time(NULL); + time_t next_change = 0; + + if (!info || !policy) { + return; + } + + if (already_expired) { + *already_expired = false; + } + + /* accounts with WBC_ACB_PWNOEXP set never receive a warning */ + if (info->acct_flags & WBC_ACB_PWNOEXP) { + return; + } + + /* no point in sending a warning if this is a grace logon */ + if (PAM_WB_GRACE_LOGON(info->user_flags)) { + return; + } + + /* check if the info3 must change timestamp has been set */ + next_change = info->pass_must_change_time; + + if (_pam_send_password_expiry_message(ctx, next_change, now, + warn_pwd_expire, + already_expired)) { + return; + } + + /* now check for the global password policy */ + /* good catch from Ralf Haferkamp: an expiry of "never" is translated + * to -1 */ + if (policy->expire <= 0) { + return; + } + + next_change = info->pass_last_set_time + policy->expire; + + if (_pam_send_password_expiry_message(ctx, next_change, now, + warn_pwd_expire, + already_expired)) { + return; + } + + /* no warning sent */ +} + +#define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) + +/** + * Append a string, making sure not to overflow and to always return a + * NULL-terminated string. + * + * @param dest Destination string buffer (must already be NULL-terminated). + * @param src Source string buffer. + * @param dest_buffer_size Size of dest buffer in bytes. + * + * @return false if dest buffer is not big enough (no bytes copied), true on + * success. + */ + +static bool safe_append_string(char *dest, + const char *src, + int dest_buffer_size) +{ + int dest_length = strlen(dest); + int src_length = strlen(src); + + if (dest_length + src_length + 1 > dest_buffer_size) { + return false; + } + + memcpy(dest + dest_length, src, src_length + 1); + return true; +} + +/** + * Convert a names into a SID string, appending it to a buffer. + * + * @param ctx PAM winbind context. + * @param user User in PAM request. + * @param name Name to convert. + * @param sid_list_buffer Where to append the string sid. + * @param sid_list_buffer Size of sid_list_buffer (in bytes). + * + * @return false on failure, true on success. + */ +static bool winbind_name_to_sid_string(struct pwb_context *ctx, + const char *user, + const char *name, + char *sid_list_buffer, + int sid_list_buffer_size) +{ + const char* sid_string; + + /* lookup name? */ + if (IS_SID_STRING(name)) { + sid_string = name; + } else { + wbcErr wbc_status; + struct wbcDomainSid sid; + enum wbcSidType type; + char *sid_str; + + _pam_log_debug(ctx, LOG_DEBUG, + "no sid given, looking up: %s\n", name); + + wbc_status = wbcLookupName("", name, &sid, &type); + if (!WBC_ERROR_IS_OK(wbc_status)) { + _pam_log(ctx, LOG_INFO, + "could not lookup name: %s\n", name); + return false; + } + + wbc_status = wbcSidToString(&sid, &sid_str); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbcFreeMemory(sid_str); + sid_string = sid_str; + } + + if (!safe_append_string(sid_list_buffer, sid_string, + sid_list_buffer_size)) { + return false; + } + + return true; +} + +/** + * Convert a list of names into a list of sids. + * + * @param ctx PAM winbind context. + * @param user User in PAM request. + * @param name_list List of names or string sids, separated by commas. + * @param sid_list_buffer Where to put the list of string sids. + * @param sid_list_buffer Size of sid_list_buffer (in bytes). + * + * @return false on failure, true on success. + */ +static bool winbind_name_list_to_sid_string_list(struct pwb_context *ctx, + const char *user, + const char *name_list, + char *sid_list_buffer, + int sid_list_buffer_size) +{ + bool result = false; + char *current_name = NULL; + const char *search_location; + const char *comma; + + if (sid_list_buffer_size > 0) { + sid_list_buffer[0] = 0; + } + + search_location = name_list; + while ((comma = strstr(search_location, ",")) != NULL) { + current_name = strndup(search_location, + comma - search_location); + if (NULL == current_name) { + goto out; + } + + if (!winbind_name_to_sid_string(ctx, user, + current_name, + sid_list_buffer, + sid_list_buffer_size)) { + goto out; + } + + SAFE_FREE(current_name); + + if (!safe_append_string(sid_list_buffer, ",", + sid_list_buffer_size)) { + goto out; + } + + search_location = comma + 1; + } + + if (!winbind_name_to_sid_string(ctx, user, search_location, + sid_list_buffer, + sid_list_buffer_size)) { + goto out; + } + + result = true; + +out: + SAFE_FREE(current_name); + return result; +} + +/** + * put krb5ccname variable into environment + * + * @param ctx PAM winbind context. + * @param krb5ccname env variable retrieved from winbindd. + * + * @return void. + */ + +static void _pam_setup_krb5_env(struct pwb_context *ctx, + struct wbcLogonUserInfo *info) +{ + char var[PATH_MAX]; + int ret; + uint32_t i; + const char *krb5ccname = NULL; + + if (off(ctx->ctrl, WINBIND_KRB5_AUTH)) { + return; + } + + if (!info) { + return; + } + + for (i=0; i < info->num_blobs; i++) { + if (strcasecmp(info->blobs[i].name, "krb5ccname") == 0) { + krb5ccname = (const char *)info->blobs[i].blob.data; + break; + } + } + + if (!krb5ccname || (strlen(krb5ccname) == 0)) { + return; + } + + _pam_log_debug(ctx, LOG_DEBUG, + "request returned KRB5CCNAME: %s", krb5ccname); + + if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { + return; + } + + ret = pam_putenv(ctx->pamh, var); + if (ret) { + _pam_log(ctx, LOG_ERR, + "failed to set KRB5CCNAME to %s: %s", + var, pam_strerror(ctx->pamh, ret)); + } +} + +/** + * Copy unix username if available (further processed in PAM). + * + * @param ctx PAM winbind context + * @param user_ret A pointer that holds a pointer to a string + * @param unix_username A username + * + * @return void. + */ + +static void _pam_setup_unix_username(struct pwb_context *ctx, + char **user_ret, + struct wbcLogonUserInfo *info) +{ + const char *unix_username = NULL; + uint32_t i; + + if (!user_ret || !info) { + return; + } + + for (i=0; i < info->num_blobs; i++) { + if (strcasecmp(info->blobs[i].name, "unix_username") == 0) { + unix_username = (const char *)info->blobs[i].blob.data; + break; + } + } + + if (!unix_username || !unix_username[0]) { + return; + } + + *user_ret = strdup(unix_username); +} + +/** + * Set string into the PAM stack. + * + * @param ctx PAM winbind context. + * @param data_name Key name for pam_set_data. + * @param value String value. + * + * @return void. + */ + +static void _pam_set_data_string(struct pwb_context *ctx, + const char *data_name, + const char *value) +{ + int ret; + + if (!data_name || !value || (strlen(data_name) == 0) || + (strlen(value) == 0)) { + return; + } + + ret = pam_set_data(ctx->pamh, data_name, talloc_strdup(NULL, value), + _pam_winbind_cleanup_func); + if (ret) { + _pam_log_debug(ctx, LOG_DEBUG, + "Could not set data %s: %s\n", + data_name, pam_strerror(ctx->pamh, ret)); + } +} + +/** + * Set info3 strings into the PAM stack. + * + * @param ctx PAM winbind context. + * @param data_name Key name for pam_set_data. + * @param value String value. + * + * @return void. + */ + +static void _pam_set_data_info3(struct pwb_context *ctx, + const struct wbcAuthUserInfo *info) +{ + _pam_set_data_string(ctx, PAM_WINBIND_HOMEDIR, + info->home_directory); + _pam_set_data_string(ctx, PAM_WINBIND_LOGONSCRIPT, + info->logon_script); + _pam_set_data_string(ctx, PAM_WINBIND_LOGONSERVER, + info->logon_server); + _pam_set_data_string(ctx, PAM_WINBIND_PROFILEPATH, + info->profile_path); +} + +/** + * Free info3 strings in the PAM stack. + * + * @param pamh PAM handle + * + * @return void. + */ + +static void _pam_free_data_info3(pam_handle_t *pamh) +{ + pam_set_data(pamh, PAM_WINBIND_HOMEDIR, NULL, NULL); + pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, NULL, NULL); + pam_set_data(pamh, PAM_WINBIND_LOGONSERVER, NULL, NULL); + pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, NULL, NULL); +} + +/** + * Send PAM_ERROR_MSG for cached or grace logons. + * + * @param ctx PAM winbind context. + * @param username User in PAM request. + * @param info3_user_flgs Info3 flags containing logon type bits. + * + * @return void. + */ + +static void _pam_warn_logon_type(struct pwb_context *ctx, + const char *username, + uint32_t info3_user_flgs) +{ + /* inform about logon type */ + if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { + + _make_remark(ctx, PAM_ERROR_MSG, + _("Grace login. " + "Please change your password as soon you're " + "online again")); + _pam_log_debug(ctx, LOG_DEBUG, + "User %s logged on using grace logon\n", + username); + + } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { + + _make_remark(ctx, PAM_ERROR_MSG, + _("Domain Controller unreachable, " + "using cached credentials instead. " + "Network resources may be unavailable")); + _pam_log_debug(ctx, LOG_DEBUG, + "User %s logged on using cached credentials\n", + username); + } +} + +/** + * Send PAM_ERROR_MSG for krb5 errors. + * + * @param ctx PAM winbind context. + * @param username User in PAM request. + * @param info3_user_flgs Info3 flags containing logon type bits. + * + * @return void. + */ + +static void _pam_warn_krb5_failure(struct pwb_context *ctx, + const char *username, + uint32_t info3_user_flgs) +{ + if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { + _make_remark(ctx, PAM_ERROR_MSG, + _("Failed to establish your Kerberos Ticket cache " + "due time differences\n" + "with the domain controller. " + "Please verify the system time.\n")); + _pam_log_debug(ctx, LOG_DEBUG, + "User %s: Clock skew when getting Krb5 TGT\n", + username); + } +} + +static bool _pam_check_remark_auth_err(struct pwb_context *ctx, + const struct wbcAuthErrorInfo *e, + const char *nt_status_string, + int *pam_error) +{ + const char *ntstatus = NULL; + const char *error_string = NULL; + + if (!e || !pam_error) { + return false; + } + + ntstatus = e->nt_string; + if (!ntstatus) { + return false; + } + + if (strcasecmp(ntstatus, nt_status_string) == 0) { + + error_string = _get_ntstatus_error_string(nt_status_string); + if (error_string) { + _make_remark(ctx, PAM_ERROR_MSG, error_string); + *pam_error = e->pam_error; + return true; + } + + if (e->display_string) { + _make_remark(ctx, PAM_ERROR_MSG, e->display_string); + *pam_error = e->pam_error; + return true; + } + + _make_remark(ctx, PAM_ERROR_MSG, nt_status_string); + *pam_error = e->pam_error; + + return true; + } + + return false; +}; + +/** + * Compose Password Restriction String for a PAM_ERROR_MSG conversation. + * + * @param i The wbcUserPasswordPolicyInfo struct. + * + * @return string (caller needs to talloc_free). + */ + +static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx, + struct wbcUserPasswordPolicyInfo *i) +{ + char *str = NULL; + + if (!i) { + goto failed; + } + + str = talloc_asprintf(ctx, _("Your password ")); + if (!str) { + goto failed; + } + + if (i->min_length_password > 0) { + str = talloc_asprintf_append(str, + _("must be at least %d characters; "), + i->min_length_password); + if (!str) { + goto failed; + } + } + + if (i->password_history > 0) { + str = talloc_asprintf_append(str, + _("cannot repeat any of your previous %d " + "passwords; "), + i->password_history); + if (!str) { + goto failed; + } + } + + if (i->password_properties & WBC_DOMAIN_PASSWORD_COMPLEX) { + str = talloc_asprintf_append(str, + _("must contain capitals, numerals " + "or punctuation; " + "and cannot contain your account " + "or full name; ")); + if (!str) { + goto failed; + } + } + + str = talloc_asprintf_append(str, + _("Please type a different password. " + "Type a password which meets these requirements in " + "both text boxes.")); + if (!str) { + goto failed; + } + + return str; + + failed: + TALLOC_FREE(str); + return NULL; +} + +static int _pam_create_homedir(struct pwb_context *ctx, + const char *dirname, + mode_t mode) +{ + struct stat sbuf; + + if (stat(dirname, &sbuf) == 0) { + return PAM_SUCCESS; + } + + if (mkdir(dirname, mode) != 0) { + + _make_remark_format(ctx, PAM_TEXT_INFO, + _("Creating directory: %s failed: %s"), + dirname, strerror(errno)); + _pam_log(ctx, LOG_ERR, "could not create dir: %s (%s)", + dirname, strerror(errno)); + return PAM_PERM_DENIED; + } + + return PAM_SUCCESS; +} + +static int _pam_chown_homedir(struct pwb_context *ctx, + const char *dirname, + uid_t uid, + gid_t gid) +{ + if (chown(dirname, uid, gid) != 0) { + _pam_log(ctx, LOG_ERR, "failed to chown user homedir: %s (%s)", + dirname, strerror(errno)); + return PAM_PERM_DENIED; + } + + return PAM_SUCCESS; +} + +static int _pam_mkhomedir(struct pwb_context *ctx) +{ + struct passwd *pwd = NULL; + char *token = NULL; + char *create_dir = NULL; + char *user_dir = NULL; + int ret; + const char *username; + mode_t mode = 0700; + char *safe_ptr = NULL; + char *p = NULL; + + /* Get the username */ + ret = pam_get_user(ctx->pamh, &username, NULL); + if ((ret != PAM_SUCCESS) || (!username)) { + _pam_log_debug(ctx, LOG_DEBUG, "can not get the username"); + return PAM_SERVICE_ERR; + } + + pwd = getpwnam(username); + if (pwd == NULL) { + _pam_log_debug(ctx, LOG_DEBUG, "can not get the username"); + return PAM_USER_UNKNOWN; + } + _pam_log_debug(ctx, LOG_DEBUG, "homedir is: %s", pwd->pw_dir); + + ret = _pam_create_homedir(ctx, pwd->pw_dir, 0700); + if (ret == PAM_SUCCESS) { + ret = _pam_chown_homedir(ctx, pwd->pw_dir, + pwd->pw_uid, + pwd->pw_gid); + } + + if (ret == PAM_SUCCESS) { + return ret; + } + + /* maybe we need to create parent dirs */ + create_dir = talloc_strdup(ctx, "/"); + if (!create_dir) { + return PAM_BUF_ERR; + } + + /* find final directory */ + user_dir = strrchr(pwd->pw_dir, '/'); + if (!user_dir) { + return PAM_BUF_ERR; + } + user_dir++; + + _pam_log(ctx, LOG_DEBUG, "final directory: %s", user_dir); + + p = pwd->pw_dir; + + while ((token = strtok_r(p, "/", &safe_ptr)) != NULL) { + + mode = 0755; + + p = NULL; + + _pam_log_debug(ctx, LOG_DEBUG, "token is %s", token); + + create_dir = talloc_asprintf_append(create_dir, "%s/", token); + if (!create_dir) { + return PAM_BUF_ERR; + } + _pam_log_debug(ctx, LOG_DEBUG, "current_dir is %s", create_dir); + + if (strcmp(token, user_dir) == 0) { + _pam_log_debug(ctx, LOG_DEBUG, "assuming last directory: %s", token); + mode = 0700; + } + + ret = _pam_create_homedir(ctx, create_dir, mode); + if (ret) { + return ret; + } + } + + return _pam_chown_homedir(ctx, create_dir, + pwd->pw_uid, + pwd->pw_gid); +} + +/* talk to winbindd */ +static int winbind_auth_request(struct pwb_context *ctx, + const char *user, + const char *pass, + const char *member, + const char *cctype, + const int warn_pwd_expire, + struct wbcAuthErrorInfo **p_error, + struct wbcLogonUserInfo **p_info, + struct wbcUserPasswordPolicyInfo **p_policy, + time_t *pwd_last_set, + char **user_ret) +{ + wbcErr wbc_status; + + struct wbcLogonUserParams logon; + char membership_of[1024]; + uid_t user_uid = -1; + uint32_t flags = WBFLAG_PAM_INFO3_TEXT | + WBFLAG_PAM_GET_PWD_POLICY; + + struct wbcLogonUserInfo *info = NULL; + struct wbcAuthUserInfo *user_info = NULL; + struct wbcAuthErrorInfo *error = NULL; + struct wbcUserPasswordPolicyInfo *policy = NULL; + + int ret = PAM_AUTH_ERR; + int i; + const char *codes[] = { + "NT_STATUS_PASSWORD_EXPIRED", + "NT_STATUS_PASSWORD_MUST_CHANGE", + "NT_STATUS_INVALID_WORKSTATION", + "NT_STATUS_INVALID_LOGON_HOURS", + "NT_STATUS_ACCOUNT_EXPIRED", + "NT_STATUS_ACCOUNT_DISABLED", + "NT_STATUS_ACCOUNT_LOCKED_OUT", + "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", + "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", + "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + "NT_STATUS_NO_LOGON_SERVERS", + "NT_STATUS_WRONG_PASSWORD", + "NT_STATUS_ACCESS_DENIED" + }; + + if (pwd_last_set) { + *pwd_last_set = 0; + } + + /* Krb5 auth always has to go against the KDC of the user's realm */ + + if (ctx->ctrl & WINBIND_KRB5_AUTH) { + flags |= WBFLAG_PAM_CONTACT_TRUSTDOM; + } + + if (ctx->ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { + struct passwd *pwd = NULL; + + pwd = getpwnam(user); + if (pwd == NULL) { + return PAM_USER_UNKNOWN; + } + user_uid = pwd->pw_uid; + } + + if (ctx->ctrl & WINBIND_KRB5_AUTH) { + + _pam_log_debug(ctx, LOG_DEBUG, + "enabling krb5 login flag\n"); + + flags |= WBFLAG_PAM_KRB5 | + WBFLAG_PAM_FALLBACK_AFTER_KRB5; + } + + if (ctx->ctrl & WINBIND_CACHED_LOGIN) { + _pam_log_debug(ctx, LOG_DEBUG, + "enabling cached login flag\n"); + flags |= WBFLAG_PAM_CACHED_LOGIN; + } + + if (user_ret) { + *user_ret = NULL; + flags |= WBFLAG_PAM_UNIX_NAME; + } + + if (cctype != NULL) { + _pam_log_debug(ctx, LOG_DEBUG, + "enabling request for a %s krb5 ccache\n", + cctype); + } + + if (member != NULL) { + + ZERO_STRUCT(membership_of); + + if (!winbind_name_list_to_sid_string_list(ctx, user, member, + membership_of, + sizeof(membership_of))) { + _pam_log_debug(ctx, LOG_ERR, + "failed to serialize membership of sid " + "\"%s\"\n", member); + return PAM_AUTH_ERR; + } + } + + ZERO_STRUCT(logon); + + logon.username = user; + logon.password = pass; + + if (cctype) { + wbc_status = wbcAddNamedBlob(&logon.num_blobs, + &logon.blobs, + "krb5_cc_type", + 0, + (uint8_t *)cctype, + strlen(cctype)+1); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto done; + } + } + + wbc_status = wbcAddNamedBlob(&logon.num_blobs, + &logon.blobs, + "flags", + 0, + (uint8_t *)&flags, + sizeof(flags)); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto done; + } + + wbc_status = wbcAddNamedBlob(&logon.num_blobs, + &logon.blobs, + "user_uid", + 0, + (uint8_t *)&user_uid, + sizeof(user_uid)); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto done; + } + + if (member) { + wbc_status = wbcAddNamedBlob(&logon.num_blobs, + &logon.blobs, + "membership_of", + 0, + (uint8_t *)membership_of, + sizeof(membership_of)); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto done; + } + } + + wbc_status = wbcLogonUser(&logon, &info, &error, &policy); + ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status, + user, "wbcLogonUser"); + wbcFreeMemory(logon.blobs); + logon.blobs = NULL; + + if (info && info->info) { + user_info = info->info; + } + + if (pwd_last_set && user_info) { + *pwd_last_set = user_info->pass_last_set_time; + } + + if (p_info && info) { + *p_info = info; + } + + if (p_policy && policy) { + *p_policy = policy; + } + + if (p_error && error) { + /* We want to process the error in the caller. */ + *p_error = error; + return ret; + } + + for (i=0; ipass_last_set_time; + + _pam_log_debug(ctx, LOG_DEBUG, + "Password has expired " + "(Password was last set: %lld, " + "the policy says it should expire here " + "%lld (now it's: %lu))\n", + (long long int)last_set, + (long long int)last_set + + policy->expire, + time(NULL)); + + return PAM_AUTHTOK_EXPIRED; + } + + /* inform about logon type */ + _pam_warn_logon_type(ctx, user, user_info->user_flags); + + /* inform about krb5 failures */ + _pam_warn_krb5_failure(ctx, user, user_info->user_flags); + + /* set some info3 info for other modules in the stack */ + _pam_set_data_info3(ctx, user_info); + + /* put krb5ccname into env */ + _pam_setup_krb5_env(ctx, info); + + /* If winbindd returned a username, return the pointer to it + * here. */ + _pam_setup_unix_username(ctx, user_ret, info); + } + + done: + if (logon.blobs) { + wbcFreeMemory(logon.blobs); + } + if (info && info->blobs) { + wbcFreeMemory(info->blobs); + } + if (error && !p_error) { + wbcFreeMemory(error); + } + if (info && !p_info) { + wbcFreeMemory(info); + } + if (policy && !p_policy) { + wbcFreeMemory(policy); + } + + return ret; +} + +/* talk to winbindd */ +static int winbind_chauthtok_request(struct pwb_context *ctx, + const char *user, + const char *oldpass, + const char *newpass, + time_t pwd_last_set) +{ + wbcErr wbc_status; + struct wbcChangePasswordParams params; + struct wbcAuthErrorInfo *error = NULL; + struct wbcUserPasswordPolicyInfo *policy = NULL; + enum wbcPasswordChangeRejectReason reject_reason = -1; + uint32_t flags = 0; + + int i; + const char *codes[] = { + "NT_STATUS_BACKUP_CONTROLLER", + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + "NT_STATUS_NO_LOGON_SERVERS", + "NT_STATUS_ACCESS_DENIED", + "NT_STATUS_PWD_TOO_SHORT", /* TODO: tell the min pwd length ? */ + "NT_STATUS_PWD_TOO_RECENT", /* TODO: tell the minage ? */ + "NT_STATUS_PWD_HISTORY_CONFLICT" /* TODO: tell the history length ? */ + }; + int ret = PAM_AUTH_ERR; + + ZERO_STRUCT(params); + + if (ctx->ctrl & WINBIND_KRB5_AUTH) { + flags |= WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; + } + + if (ctx->ctrl & WINBIND_CACHED_LOGIN) { + flags |= WBFLAG_PAM_CACHED_LOGIN; + } + + params.account_name = user; + params.level = WBC_AUTH_USER_LEVEL_PLAIN; + params.old_password.plaintext = oldpass; + params.new_password.plaintext = newpass; + params.flags = flags; + + wbc_status = wbcChangeUserPasswordEx(¶ms, &error, &reject_reason, &policy); + ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status, + user, "wbcChangeUserPasswordEx"); + + if (WBC_ERROR_IS_OK(wbc_status)) { + _pam_log(ctx, LOG_NOTICE, + "user '%s' password changed", user); + return PAM_SUCCESS; + } + + if (!error) { + wbcFreeMemory(policy); + return ret; + } + + for (i=0; int_string, + "NT_STATUS_PASSWORD_RESTRICTION")) { + + char *pwd_restriction_string = NULL; + SMB_TIME_T min_pwd_age = 0; + + if (policy) { + min_pwd_age = policy->min_passwordage; + } + + /* FIXME: avoid to send multiple PAM messages after another */ + switch (reject_reason) { + case -1: + break; + case WBC_PWD_CHANGE_REJECT_OTHER: + if ((min_pwd_age > 0) && + (pwd_last_set + min_pwd_age > time(NULL))) { + PAM_WB_REMARK_DIRECT(ctx, + "NT_STATUS_PWD_TOO_RECENT"); + } + break; + case WBC_PWD_CHANGE_REJECT_TOO_SHORT: + PAM_WB_REMARK_DIRECT(ctx, + "NT_STATUS_PWD_TOO_SHORT"); + break; + case WBC_PWD_CHANGE_REJECT_IN_HISTORY: + PAM_WB_REMARK_DIRECT(ctx, + "NT_STATUS_PWD_HISTORY_CONFLICT"); + break; + case WBC_PWD_CHANGE_REJECT_COMPLEXITY: + _make_remark(ctx, PAM_ERROR_MSG, + _("Password does not meet " + "complexity requirements")); + break; + default: + _pam_log_debug(ctx, LOG_DEBUG, + "unknown password change " + "reject reason: %d", + reject_reason); + break; + } + + pwd_restriction_string = + _pam_compose_pwd_restriction_string(ctx, policy); + if (pwd_restriction_string) { + _make_remark(ctx, PAM_ERROR_MSG, + pwd_restriction_string); + TALLOC_FREE(pwd_restriction_string); + } + } + done: + wbcFreeMemory(error); + wbcFreeMemory(policy); + + return ret; +} + +/* + * Checks if a user has an account + * + * return values: + * 1 = User not found + * 0 = OK + * -1 = System error + */ +static int valid_user(struct pwb_context *ctx, + const char *user) +{ + /* check not only if the user is available over NSS calls, also make + * sure it's really a winbind user, this is important when stacking PAM + * modules in the 'account' or 'password' facility. */ + + wbcErr wbc_status; + struct passwd *pwd = NULL; + struct passwd *wb_pwd = NULL; + + pwd = getpwnam(user); + if (pwd == NULL) { + return 1; + } + + wbc_status = wbcGetpwnam(user, &wb_pwd); + wbcFreeMemory(wb_pwd); + if (!WBC_ERROR_IS_OK(wbc_status)) { + _pam_log(ctx, LOG_DEBUG, "valid_user: wbcGetpwnam gave %s\n", + wbcErrorString(wbc_status)); + } + + switch (wbc_status) { + case WBC_ERR_UNKNOWN_USER: + return 1; + case WBC_ERR_SUCCESS: + return 0; + default: + break; + } + return -1; +} + +static char *_pam_delete(register char *xx) +{ + _pam_overwrite(xx); + _pam_drop(xx); + return NULL; +} + +/* + * obtain a password from the user + */ + +static int _winbind_read_password(struct pwb_context *ctx, + unsigned int ctrl, + const char *comment, + const char *prompt1, + const char *prompt2, + const char **pass) +{ + int authtok_flag; + int retval; + const char *item; + char *token; + + _pam_log(ctx, LOG_DEBUG, "getting password (0x%08x)", ctrl); + + /* + * make sure nothing inappropriate gets returned + */ + + *pass = token = NULL; + + /* + * which authentication token are we getting? + */ + + if (on(WINBIND__OLD_PASSWORD, ctrl)) { + authtok_flag = PAM_OLDAUTHTOK; + } else { + authtok_flag = PAM_AUTHTOK; + } + + /* + * should we obtain the password from a PAM item ? + */ + + if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || + on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { + retval = _pam_get_item(ctx->pamh, authtok_flag, &item); + if (retval != PAM_SUCCESS) { + /* very strange. */ + _pam_log(ctx, LOG_ALERT, + "pam_get_item returned error " + "to unix-read-password"); + return retval; + } else if (item != NULL) { /* we have a password! */ + *pass = item; + item = NULL; + _pam_log(ctx, LOG_DEBUG, + "pam_get_item returned a password"); + return PAM_SUCCESS; + } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ + } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) + && off(WINBIND__OLD_PASSWORD, ctrl)) { + return PAM_AUTHTOK_RECOVER_ERR; + } + } + /* + * getting here implies we will have to get the password from the + * user directly. + */ + + { + struct pam_message msg[3], *pmsg[3]; + struct pam_response *resp; + int i, replies; + + /* prepare to converse */ + + if (comment != NULL && off(ctrl, WINBIND_SILENT)) { + pmsg[0] = &msg[0]; + msg[0].msg_style = PAM_TEXT_INFO; + msg[0].msg = discard_const_p(char, comment); + i = 1; + } else { + i = 0; + } + + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = discard_const_p(char, prompt1); + replies = 1; + + if (prompt2 != NULL) { + pmsg[i] = &msg[i]; + msg[i].msg_style = PAM_PROMPT_ECHO_OFF; + msg[i++].msg = discard_const_p(char, prompt2); + ++replies; + } + /* so call the conversation expecting i responses */ + resp = NULL; + retval = converse(ctx->pamh, i, pmsg, &resp); + if (resp == NULL) { + if (retval == PAM_SUCCESS) { + retval = PAM_AUTHTOK_RECOVER_ERR; + } + goto done; + } + if (retval != PAM_SUCCESS) { + _pam_drop_reply(resp, i); + goto done; + } + + /* interpret the response */ + + token = x_strdup(resp[i - replies].resp); + if (!token) { + _pam_log(ctx, LOG_NOTICE, + "could not recover " + "authentication token"); + retval = PAM_AUTHTOK_RECOVER_ERR; + goto done; + } + + if (replies == 2) { + /* verify that password entered correctly */ + if (!resp[i - 1].resp || + strcmp(token, resp[i - 1].resp)) { + _pam_delete(token); /* mistyped */ + retval = PAM_AUTHTOK_RECOVER_ERR; + _make_remark(ctx, PAM_ERROR_MSG, + MISTYPED_PASS); + } + } + + /* + * tidy up the conversation (resp_retcode) is ignored + * -- what is it for anyway? AGM + */ + _pam_drop_reply(resp, i); + } + + done: + if (retval != PAM_SUCCESS) { + _pam_log_debug(ctx, LOG_DEBUG, + "unable to obtain a password"); + return retval; + } + /* 'token' is the entered password */ + + /* we store this password as an item */ + + retval = pam_set_item(ctx->pamh, authtok_flag, token); + _pam_delete(token); /* clean it up */ + if (retval != PAM_SUCCESS || + (retval = _pam_get_item(ctx->pamh, authtok_flag, &item)) != PAM_SUCCESS) { + + _pam_log(ctx, LOG_CRIT, "error manipulating password"); + return retval; + + } + + *pass = item; + item = NULL; /* break link to password */ + + return PAM_SUCCESS; +} + +static const char *get_conf_item_string(struct pwb_context *ctx, + const char *item, + int config_flag) +{ + int i = 0; + const char *parm_opt = NULL; + + if (!(ctx->ctrl & config_flag)) { + goto out; + } + + /* let the pam opt take precedence over the pam_winbind.conf option */ + for (i=0; iargc; i++) { + + if ((strncmp(ctx->argv[i], item, strlen(item)) == 0)) { + char *p; + + if ((p = strchr(ctx->argv[i], '=')) == NULL) { + _pam_log(ctx, LOG_INFO, + "no \"=\" delimiter for \"%s\" found\n", + item); + goto out; + } + _pam_log_debug(ctx, LOG_INFO, + "PAM config: %s '%s'\n", item, p+1); + return p + 1; + } + } + + if (ctx->dict) { + char *key = NULL; + + key = talloc_asprintf(ctx, "global:%s", item); + if (!key) { + goto out; + } + + parm_opt = iniparser_getstr(ctx->dict, key); + TALLOC_FREE(key); + + _pam_log_debug(ctx, LOG_INFO, "CONFIG file: %s '%s'\n", + item, parm_opt); + } +out: + return parm_opt; +} + +static int get_config_item_int(struct pwb_context *ctx, + const char *item, + int config_flag) +{ + int i, parm_opt = -1; + + if (!(ctx->ctrl & config_flag)) { + goto out; + } + + /* let the pam opt take precedence over the pam_winbind.conf option */ + for (i = 0; i < ctx->argc; i++) { + + if ((strncmp(ctx->argv[i], item, strlen(item)) == 0)) { + char *p; + + if ((p = strchr(ctx->argv[i], '=')) == NULL) { + _pam_log(ctx, LOG_INFO, + "no \"=\" delimiter for \"%s\" found\n", + item); + goto out; + } + parm_opt = atoi(p + 1); + _pam_log_debug(ctx, LOG_INFO, + "PAM config: %s '%d'\n", + item, parm_opt); + return parm_opt; + } + } + + if (ctx->dict) { + char *key = NULL; + + key = talloc_asprintf(ctx, "global:%s", item); + if (!key) { + goto out; + } + + parm_opt = iniparser_getint(ctx->dict, key, -1); + TALLOC_FREE(key); + + _pam_log_debug(ctx, LOG_INFO, + "CONFIG file: %s '%d'\n", + item, parm_opt); + } +out: + return parm_opt; +} + +static const char *get_krb5_cc_type_from_config(struct pwb_context *ctx) +{ + return get_conf_item_string(ctx, "krb5_ccache_type", + WINBIND_KRB5_CCACHE_TYPE); +} + +static const char *get_member_from_config(struct pwb_context *ctx) +{ + const char *ret = NULL; + ret = get_conf_item_string(ctx, "require_membership_of", + WINBIND_REQUIRED_MEMBERSHIP); + if (ret) { + return ret; + } + return get_conf_item_string(ctx, "require-membership-of", + WINBIND_REQUIRED_MEMBERSHIP); +} + +static int get_warn_pwd_expire_from_config(struct pwb_context *ctx) +{ + int ret; + ret = get_config_item_int(ctx, "warn_pwd_expire", + WINBIND_WARN_PWD_EXPIRE); + /* no or broken setting */ + if (ret <= 0) { + return DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES; + } + return ret; +} + +/** + * Retrieve the winbind separator. + * + * @param ctx PAM winbind context. + * + * @return string separator character. NULL on failure. + */ + +static char winbind_get_separator(struct pwb_context *ctx) +{ + wbcErr wbc_status; + static struct wbcInterfaceDetails *details = NULL; + + wbc_status = wbcInterfaceDetails(&details); + if (!WBC_ERROR_IS_OK(wbc_status)) { + _pam_log(ctx, LOG_ERR, + "Could not retrieve winbind interface details: %s", + wbcErrorString(wbc_status)); + return '\0'; + } + + if (!details) { + return '\0'; + } + + return details->winbind_separator; +} + + +/** + * Convert a upn to a name. + * + * @param ctx PAM winbind context. + * @param upn USer UPN to be trabslated. + * + * @return converted name. NULL pointer on failure. Caller needs to free. + */ + +static char* winbind_upn_to_username(struct pwb_context *ctx, + const char *upn) +{ + char sep; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + enum wbcSidType type; + char *domain; + char *name; + + /* This cannot work when the winbind separator = @ */ + + sep = winbind_get_separator(ctx); + if (!sep || sep == '@') { + return NULL; + } + + /* Convert the UPN to a SID */ + + wbc_status = wbcLookupName("", upn, &sid, &type); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return NULL; + } + + /* Convert the the SID back to the sAMAccountName */ + + wbc_status = wbcLookupSid(&sid, &domain, &name, &type); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return NULL; + } + + return talloc_asprintf(ctx, "%s\\%s", domain, name); +} + +static int _pam_delete_cred(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + int retval = PAM_SUCCESS; + struct pwb_context *ctx = NULL; + struct wbcLogoffUserParams logoff; + struct wbcAuthErrorInfo *error = NULL; + const char *user; + wbcErr wbc_status = WBC_ERR_SUCCESS; + + retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (retval) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("_pam_delete_cred", ctx); + + if (ctx->ctrl & WINBIND_KRB5_AUTH) { + + /* destroy the ccache here */ + + uint32_t wbc_flags = 0; + const char *ccname = NULL; + struct passwd *pwd = NULL; + + retval = pam_get_user(pamh, &user, _("Username: ")); + if (retval) { + _pam_log(ctx, LOG_ERR, + "could not identify user"); + goto out; + } + + if (user == NULL) { + _pam_log(ctx, LOG_ERR, + "username was NULL!"); + retval = PAM_USER_UNKNOWN; + goto out; + } + + _pam_log_debug(ctx, LOG_DEBUG, + "username [%s] obtained", user); + + ccname = pam_getenv(pamh, "KRB5CCNAME"); + if (ccname == NULL) { + _pam_log_debug(ctx, LOG_DEBUG, + "user has no KRB5CCNAME environment"); + } + + pwd = getpwnam(user); + if (pwd == NULL) { + retval = PAM_USER_UNKNOWN; + goto out; + } + + wbc_flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CONTACT_TRUSTDOM; + + ZERO_STRUCT(logoff); + + logoff.username = user; + + if (ccname) { + wbc_status = wbcAddNamedBlob(&logoff.num_blobs, + &logoff.blobs, + "ccfilename", + 0, + (uint8_t *)ccname, + strlen(ccname)+1); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto out; + } + } + + wbc_status = wbcAddNamedBlob(&logoff.num_blobs, + &logoff.blobs, + "flags", + 0, + (uint8_t *)&wbc_flags, + sizeof(wbc_flags)); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto out; + } + + wbc_status = wbcAddNamedBlob(&logoff.num_blobs, + &logoff.blobs, + "user_uid", + 0, + (uint8_t *)&pwd->pw_uid, + sizeof(pwd->pw_uid)); + if (!WBC_ERROR_IS_OK(wbc_status)) { + goto out; + } + + wbc_status = wbcLogoffUserEx(&logoff, &error); + retval = wbc_auth_error_to_pam_error(ctx, error, wbc_status, + user, "wbcLogoffUser"); + wbcFreeMemory(error); + wbcFreeMemory(logoff.blobs); + + if (!WBC_ERROR_IS_OK(wbc_status)) { + _pam_log(ctx, LOG_INFO, + "failed to logoff user %s: %s\n", + user, wbcErrorString(wbc_status)); + } + } + +out: + if (logoff.blobs) { + wbcFreeMemory(logoff.blobs); + } + + if (!WBC_ERROR_IS_OK(wbc_status)) { + retval = wbc_auth_error_to_pam_error(ctx, error, wbc_status, + user, "wbcLogoffUser"); + } + + /* + * Delete the krb5 ccname variable from the PAM environment + * if it was set by winbind. + */ + if (ctx->ctrl & WINBIND_KRB5_AUTH) { + pam_putenv(pamh, "KRB5CCNAME"); + } + + _PAM_LOG_FUNCTION_LEAVE("_pam_delete_cred", ctx, retval); + + TALLOC_FREE(ctx); + + return retval; +} + +PAM_EXTERN +int pam_sm_authenticate(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *username; + const char *password; + const char *member = NULL; + const char *cctype = NULL; + int warn_pwd_expire; + int retval = PAM_AUTH_ERR; + char *username_ret = NULL; + char *new_authtok_required = NULL; + char *real_username = NULL; + struct pwb_context *ctx = NULL; + + retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (retval) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", ctx); + + /* Get the username */ + retval = pam_get_user(pamh, &username, NULL); + if ((retval != PAM_SUCCESS) || (!username)) { + _pam_log_debug(ctx, LOG_DEBUG, + "can not get the username"); + retval = PAM_SERVICE_ERR; + goto out; + } + + +#if defined(AIX) + /* Decode the user name since AIX does not support logn user + names by default. The name is encoded as _#uid. */ + + if (username[0] == '_') { + uid_t id = atoi(&username[1]); + struct passwd *pw = NULL; + + if ((id!=0) && ((pw = getpwuid(id)) != NULL)) { + real_username = strdup(pw->pw_name); + } + } +#endif + + if (!real_username) { + /* Just making a copy of the username we got from PAM */ + if ((real_username = strdup(username)) == NULL) { + _pam_log_debug(ctx, LOG_DEBUG, + "memory allocation failure when copying " + "username"); + retval = PAM_SERVICE_ERR; + goto out; + } + } + + /* Maybe this was a UPN */ + + if (strchr(real_username, '@') != NULL) { + char *samaccountname = NULL; + + samaccountname = winbind_upn_to_username(ctx, + real_username); + if (samaccountname) { + free(real_username); + real_username = strdup(samaccountname); + } + } + + retval = _winbind_read_password(ctx, ctx->ctrl, NULL, + _("Password: "), NULL, + &password); + + if (retval != PAM_SUCCESS) { + _pam_log(ctx, LOG_ERR, + "Could not retrieve user's password"); + retval = PAM_AUTHTOK_ERR; + goto out; + } + + /* Let's not give too much away in the log file */ + +#ifdef DEBUG_PASSWORD + _pam_log_debug(ctx, LOG_INFO, + "Verify user '%s' with password '%s'", + real_username, password); +#else + _pam_log_debug(ctx, LOG_INFO, + "Verify user '%s'", real_username); +#endif + + member = get_member_from_config(ctx); + cctype = get_krb5_cc_type_from_config(ctx); + warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); + + /* Now use the username to look up password */ + retval = winbind_auth_request(ctx, real_username, password, + member, cctype, warn_pwd_expire, + NULL, NULL, NULL, + NULL, &username_ret); + + if (retval == PAM_NEW_AUTHTOK_REQD || + retval == PAM_AUTHTOK_EXPIRED) { + + char *new_authtok_required_during_auth = NULL; + + new_authtok_required = talloc_asprintf(NULL, "%d", retval); + if (!new_authtok_required) { + retval = PAM_BUF_ERR; + goto out; + } + + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, + new_authtok_required, + _pam_winbind_cleanup_func); + + retval = PAM_SUCCESS; + + new_authtok_required_during_auth = talloc_asprintf(NULL, "%d", true); + if (!new_authtok_required_during_auth) { + retval = PAM_BUF_ERR; + goto out; + } + + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + new_authtok_required_during_auth, + _pam_winbind_cleanup_func); + + goto out; + } + +out: + if (username_ret) { + pam_set_item (pamh, PAM_USER, username_ret); + _pam_log_debug(ctx, LOG_INFO, + "Returned user was '%s'", username_ret); + free(username_ret); + } + + if (real_username) { + free(real_username); + } + + if (!new_authtok_required) { + pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); + } + + if (retval != PAM_SUCCESS) { + _pam_free_data_info3(pamh); + } + + _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", ctx, retval); + + TALLOC_FREE(ctx); + + return retval; +} + +PAM_EXTERN +int pam_sm_setcred(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + int ret = PAM_SYSTEM_ERR; + struct pwb_context *ctx = NULL; + + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", ctx); + + switch (flags & ~PAM_SILENT) { + + case PAM_DELETE_CRED: + ret = _pam_delete_cred(pamh, flags, argc, argv); + break; + case PAM_REFRESH_CRED: + _pam_log_debug(ctx, LOG_WARNING, + "PAM_REFRESH_CRED not implemented"); + ret = PAM_SUCCESS; + break; + case PAM_REINITIALIZE_CRED: + _pam_log_debug(ctx, LOG_WARNING, + "PAM_REINITIALIZE_CRED not implemented"); + ret = PAM_SUCCESS; + break; + case PAM_ESTABLISH_CRED: + _pam_log_debug(ctx, LOG_WARNING, + "PAM_ESTABLISH_CRED not implemented"); + ret = PAM_SUCCESS; + break; + default: + ret = PAM_SYSTEM_ERR; + break; + } + + out: + + _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", ctx, ret); + + TALLOC_FREE(ctx); + + return ret; +} + +/* + * Account management. We want to verify that the account exists + * before returning PAM_SUCCESS + */ +PAM_EXTERN +int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + const char *username; + int ret = PAM_USER_UNKNOWN; + void *tmp = NULL; + struct pwb_context *ctx = NULL; + + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", ctx); + + + /* Get the username */ + ret = pam_get_user(pamh, &username, NULL); + if ((ret != PAM_SUCCESS) || (!username)) { + _pam_log_debug(ctx, LOG_DEBUG, + "can not get the username"); + ret = PAM_SERVICE_ERR; + goto out; + } + + /* Verify the username */ + ret = valid_user(ctx, username); + switch (ret) { + case -1: + /* some sort of system error. The log was already printed */ + ret = PAM_SERVICE_ERR; + goto out; + case 1: + /* the user does not exist */ + _pam_log_debug(ctx, LOG_NOTICE, "user '%s' not found", + username); + if (ctx->ctrl & WINBIND_UNKNOWN_OK_ARG) { + ret = PAM_IGNORE; + goto out; + } + ret = PAM_USER_UNKNOWN; + goto out; + case 0: + pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, + (const void **)&tmp); + if (tmp != NULL) { + ret = atoi((const char *)tmp); + switch (ret) { + case PAM_AUTHTOK_EXPIRED: + /* fall through, since new token is required in this case */ + case PAM_NEW_AUTHTOK_REQD: + _pam_log(ctx, LOG_WARNING, + "pam_sm_acct_mgmt success but %s is set", + PAM_WINBIND_NEW_AUTHTOK_REQD); + _pam_log(ctx, LOG_NOTICE, + "user '%s' needs new password", + username); + /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ + ret = PAM_NEW_AUTHTOK_REQD; + goto out; + default: + _pam_log(ctx, LOG_WARNING, + "pam_sm_acct_mgmt success"); + _pam_log(ctx, LOG_NOTICE, + "user '%s' granted access", username); + ret = PAM_SUCCESS; + goto out; + } + } + + /* Otherwise, the authentication looked good */ + _pam_log(ctx, LOG_NOTICE, + "user '%s' granted access", username); + ret = PAM_SUCCESS; + goto out; + default: + /* we don't know anything about this return value */ + _pam_log(ctx, LOG_ERR, + "internal module error (ret = %d, user = '%s')", + ret, username); + ret = PAM_SERVICE_ERR; + goto out; + } + + /* should not be reached */ + ret = PAM_IGNORE; + + out: + + _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", ctx, ret); + + TALLOC_FREE(ctx); + + return ret; +} + +PAM_EXTERN +int pam_sm_open_session(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + int ret = PAM_SUCCESS; + struct pwb_context *ctx = NULL; + + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", ctx); + + if (ctx->ctrl & WINBIND_MKHOMEDIR) { + /* check and create homedir */ + ret = _pam_mkhomedir(ctx); + } + out: + _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", ctx, ret); + + TALLOC_FREE(ctx); + + return ret; +} + +PAM_EXTERN +int pam_sm_close_session(pam_handle_t *pamh, int flags, + int argc, const char **argv) +{ + int ret = PAM_SUCCESS; + struct pwb_context *ctx = NULL; + + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", ctx); + +out: + _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", ctx, ret); + + TALLOC_FREE(ctx); + + return ret; +} + +/** + * evaluate whether we need to re-authenticate with kerberos after a + * password change + * + * @param ctx PAM winbind context. + * @param user The username + * + * @return boolean Returns true if required, false if not. + */ + +static bool _pam_require_krb5_auth_after_chauthtok(struct pwb_context *ctx, + const char *user) +{ + + /* Make sure that we only do this if a) the chauthtok got initiated + * during a logon attempt (authenticate->acct_mgmt->chauthtok) b) any + * later password change via the "passwd" command if done by the user + * itself + * NB. If we login from gdm or xdm and the password expires, + * we change the password, but there is no memory cache. + * Thus, even for passthrough login, we should do the + * authentication again to update memory cache. + * --- BoYang + * */ + + char *new_authtok_reqd_during_auth = NULL; + struct passwd *pwd = NULL; + + _pam_get_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + &new_authtok_reqd_during_auth); + pam_set_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, + NULL, NULL); + + if (new_authtok_reqd_during_auth) { + return true; + } + + pwd = getpwnam(user); + if (!pwd) { + return false; + } + + if (getuid() == pwd->pw_uid) { + return true; + } + + return false; +} + + +PAM_EXTERN +int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + int argc, const char **argv) +{ + unsigned int lctrl; + int ret; + bool cached_login = false; + + /* */ + const char *user; + char *pass_old, *pass_new; + /* */ + + char *Announce; + + int retry = 0; + char *username_ret = NULL; + struct wbcAuthErrorInfo *error = NULL; + struct pwb_context *ctx = NULL; + + ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); + if (ret) { + goto out; + } + + _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", ctx); + + cached_login = (ctx->ctrl & WINBIND_CACHED_LOGIN); + + /* clearing offline bit for auth */ + ctx->ctrl &= ~WINBIND_CACHED_LOGIN; + + /* + * First get the name of a user + */ + ret = pam_get_user(pamh, &user, _("Username: ")); + if (ret) { + _pam_log(ctx, LOG_ERR, + "password - could not identify user"); + goto out; + } + + if (user == NULL) { + _pam_log(ctx, LOG_ERR, "username was NULL!"); + ret = PAM_USER_UNKNOWN; + goto out; + } + + _pam_log_debug(ctx, LOG_DEBUG, "username [%s] obtained", user); + + /* check if this is really a user in winbindd, not only in NSS */ + ret = valid_user(ctx, user); + switch (ret) { + case 1: + ret = PAM_USER_UNKNOWN; + goto out; + case -1: + ret = PAM_SYSTEM_ERR; + goto out; + default: + break; + } + + /* + * obtain and verify the current password (OLDAUTHTOK) for + * the user. + */ + + if (flags & PAM_PRELIM_CHECK) { + time_t pwdlastset_prelim = 0; + + /* instruct user what is happening */ + +#define greeting _("Changing password for") + Announce = talloc_asprintf(ctx, "%s %s", greeting, user); + if (!Announce) { + _pam_log(ctx, LOG_CRIT, + "password - out of memory"); + ret = PAM_BUF_ERR; + goto out; + } +#undef greeting + + lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD; + ret = _winbind_read_password(ctx, lctrl, + Announce, + _("(current) NT password: "), + NULL, + (const char **) &pass_old); + TALLOC_FREE(Announce); + if (ret != PAM_SUCCESS) { + _pam_log(ctx, LOG_NOTICE, + "password - (old) token not obtained"); + goto out; + } + + /* verify that this is the password for this user */ + + ret = winbind_auth_request(ctx, user, pass_old, + NULL, NULL, 0, + &error, NULL, NULL, + &pwdlastset_prelim, NULL); + + if (ret != PAM_ACCT_EXPIRED && + ret != PAM_AUTHTOK_EXPIRED && + ret != PAM_NEW_AUTHTOK_REQD && + ret != PAM_SUCCESS) { + pass_old = NULL; + goto out; + } + + pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, + (void *)pwdlastset_prelim, NULL); + + ret = pam_set_item(pamh, PAM_OLDAUTHTOK, + (const void *) pass_old); + pass_old = NULL; + if (ret != PAM_SUCCESS) { + _pam_log(ctx, LOG_CRIT, + "failed to set PAM_OLDAUTHTOK"); + } + } else if (flags & PAM_UPDATE_AUTHTOK) { + + time_t pwdlastset_update = 0; + + /* + * obtain the proposed password + */ + + /* + * get the old token back. + */ + + ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); + + if (ret != PAM_SUCCESS) { + _pam_log(ctx, LOG_NOTICE, + "user not authenticated"); + goto out; + } + + lctrl = ctx->ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; + + if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { + lctrl |= WINBIND_USE_FIRST_PASS_ARG; + } + retry = 0; + ret = PAM_AUTHTOK_ERR; + while ((ret != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { + /* + * use_authtok is to force the use of a previously entered + * password -- needed for pluggable password strength checking + */ + + ret = _winbind_read_password(ctx, lctrl, + NULL, + _("Enter new NT password: "), + _("Retype new NT password: "), + (const char **)&pass_new); + + if (ret != PAM_SUCCESS) { + _pam_log_debug(ctx, LOG_ALERT, + "password - " + "new password not obtained"); + pass_old = NULL;/* tidy up */ + goto out; + } + + /* + * At this point we know who the user is and what they + * propose as their new password. Verify that the new + * password is acceptable. + */ + + if (pass_new[0] == '\0') {/* "\0" password = NULL */ + pass_new = NULL; + } + } + + /* + * By reaching here we have approved the passwords and must now + * rebuild the password database file. + */ + _pam_get_data(pamh, PAM_WINBIND_PWD_LAST_SET, + &pwdlastset_update); + + /* + * if cached creds were enabled, make sure to set the + * WINBIND_CACHED_LOGIN bit here in order to have winbindd + * update the cached creds storage - gd + */ + if (cached_login) { + ctx->ctrl |= WINBIND_CACHED_LOGIN; + } + + ret = winbind_chauthtok_request(ctx, user, pass_old, + pass_new, pwdlastset_update); + if (ret) { + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_old = pass_new = NULL; + goto out; + } + + if (_pam_require_krb5_auth_after_chauthtok(ctx, user)) { + + const char *member = NULL; + const char *cctype = NULL; + int warn_pwd_expire; + struct wbcLogonUserInfo *info = NULL; + struct wbcUserPasswordPolicyInfo *policy = NULL; + + member = get_member_from_config(ctx); + cctype = get_krb5_cc_type_from_config(ctx); + warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); + + /* Keep WINBIND_CACHED_LOGIN bit for + * authentication after changing the password. + * This will update the cached credentials in case + * that winbindd_dual_pam_chauthtok() fails + * to update them. + * --- BoYang + * */ + + ret = winbind_auth_request(ctx, user, pass_new, + member, cctype, 0, + &error, &info, &policy, + NULL, &username_ret); + _pam_overwrite(pass_new); + _pam_overwrite(pass_old); + pass_old = pass_new = NULL; + + if (ret == PAM_SUCCESS) { + + struct wbcAuthUserInfo *user_info = NULL; + + if (info && info->info) { + user_info = info->info; + } + + /* warn a user if the password is about to + * expire soon */ + _pam_warn_password_expiry(ctx, user_info, policy, + warn_pwd_expire, + NULL); + + /* set some info3 info for other modules in the + * stack */ + _pam_set_data_info3(ctx, user_info); + + /* put krb5ccname into env */ + _pam_setup_krb5_env(ctx, info); + + if (username_ret) { + pam_set_item(pamh, PAM_USER, + username_ret); + _pam_log_debug(ctx, LOG_INFO, + "Returned user was '%s'", + username_ret); + free(username_ret); + } + + wbcFreeMemory(info); + wbcFreeMemory(policy); + } + + goto out; + } + } else { + ret = PAM_SERVICE_ERR; + } + +out: + { + /* Deal with offline errors. */ + int i; + const char *codes[] = { + "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", + "NT_STATUS_NO_LOGON_SERVERS", + "NT_STATUS_ACCESS_DENIED" + }; + + for (i=0; i 2000 + * Copyright (c) Tim Potter 2000 + * Copyright (c) Andrew Bartlettt 2002 + * Copyright (c) Guenther Deschner 2005-2008 + * Copyright (c) Jan Rêkorajski 1999. + * Copyright (c) Andrew G. Morgan 1996-8. + * Copyright (c) Alex O. Yuriev, 1996. + * Copyright (c) Cristian Gafton 1996. + * Copyright (C) Elliot Lee 1996, Red Hat Software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/nsswitch/pam_winbind.h b/nsswitch/pam_winbind.h new file mode 100644 index 0000000000..c6b2c5e726 --- /dev/null +++ b/nsswitch/pam_winbind.h @@ -0,0 +1,169 @@ +/* pam_winbind header file + (Solaris needs some macros from Linux for common PAM code) + + Shirish Kalele 2000 +*/ + +#include "../lib/replace/replace.h" +#include "system/syslog.h" +#include "system/time.h" +#include +#include "libwbclient/wbclient.h" +#include "localedir.h" + +#define MODULE_NAME "pam_winbind" +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_PASSWORD +#define PAM_SM_SESSION + +#ifndef PAM_WINBIND_CONFIG_FILE +#define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf" +#endif + +#include + +#ifdef HAVE_LIBINTL_H +#include +#endif + +#ifndef LINUX + +/* Solaris always uses dynamic pam modules */ +#define PAM_EXTERN extern +#if defined(HAVE_SECURITY_PAM_APPL_H) +#include +#elif defined(HAVE_PAM_PAM_APPL_H) +#include +#endif + +#ifndef PAM_AUTHTOK_RECOVER_ERR +#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR +#endif + +#endif /* defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD) || defined(AIX) */ + +#if defined(HAVE_SECURITY_PAM_MODULES_H) +#include +#elif defined(HAVE_PAM_PAM_MODULES_H) +#include +#endif + +#if defined(HAVE_SECURITY__PAM_MACROS_H) +#include +#elif defined(HAVE_PAM__PAM_MACROS_H) +#include +#else +/* Define required macros from (Linux PAM 0.68) security/_pam_macros.h */ +#define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \ +do { \ + int reply_i; \ + \ + for (reply_i=0; reply_i +#endif + +#define WINBIND_DEBUG_ARG 0x00000001 +#define WINBIND_USE_AUTHTOK_ARG 0x00000002 +#define WINBIND_UNKNOWN_OK_ARG 0x00000004 +#define WINBIND_TRY_FIRST_PASS_ARG 0x00000008 +#define WINBIND_USE_FIRST_PASS_ARG 0x00000010 +#define WINBIND__OLD_PASSWORD 0x00000020 +#define WINBIND_REQUIRED_MEMBERSHIP 0x00000040 +#define WINBIND_KRB5_AUTH 0x00000080 +#define WINBIND_KRB5_CCACHE_TYPE 0x00000100 +#define WINBIND_CACHED_LOGIN 0x00000200 +#define WINBIND_CONFIG_FILE 0x00000400 +#define WINBIND_SILENT 0x00000800 +#define WINBIND_DEBUG_STATE 0x00001000 +#define WINBIND_WARN_PWD_EXPIRE 0x00002000 +#define WINBIND_MKHOMEDIR 0x00004000 + +#if defined(HAVE_GETTEXT) && !defined(__LCLINT__) +#define _(string) dgettext(MODULE_NAME, string) +#else +#define _(string) string +#endif + +#define N_(string) string + +/* + * here is the string to inform the user that the new passwords they + * typed were not the same. + */ + +#define MISTYPED_PASS _("Sorry, passwords do not match") + +#define on(x, y) (x & y) +#define off(x, y) (!(x & y)) + +#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD" +#define PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH "PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH" +#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR" +#define PAM_WINBIND_LOGONSCRIPT "PAM_WINBIND_LOGONSCRIPT" +#define PAM_WINBIND_LOGONSERVER "PAM_WINBIND_LOGONSERVER" +#define PAM_WINBIND_PROFILEPATH "PAM_WINBIND_PROFILEPATH" +#define PAM_WINBIND_PWD_LAST_SET "PAM_WINBIND_PWD_LAST_SET" + +#define SECONDS_PER_DAY 86400 + +#define DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES 14 + +#include "winbind_client.h" + +#define PAM_WB_REMARK_DIRECT(c,x)\ +{\ + const char *error_string = NULL; \ + error_string = _get_ntstatus_error_string(x);\ + if (error_string != NULL) {\ + _make_remark(c, PAM_ERROR_MSG, error_string);\ + } else {\ + _make_remark(c, PAM_ERROR_MSG, x);\ + };\ +}; + +#define LOGON_KRB5_FAIL_CLOCK_SKEW 0x02000000 + +#define PAM_WB_CACHED_LOGON(x) (x & WBC_AUTH_USER_INFO_CACHED_ACCOUNT) +#define PAM_WB_KRB5_CLOCK_SKEW(x) (x & LOGON_KRB5_FAIL_CLOCK_SKEW) +#define PAM_WB_GRACE_LOGON(x) ((WBC_AUTH_USER_INFO_CACHED_ACCOUNT|WBC_AUTH_USER_INFO_GRACE_LOGON) == ( x & (WBC_AUTH_USER_INFO_CACHED_ACCOUNT|WBC_AUTH_USER_INFO_GRACE_LOGON))) + +struct pwb_context { + pam_handle_t *pamh; + int flags; + int argc; + const char **argv; + dictionary *dict; + uint32_t ctrl; +}; + +#define TALLOC_FREE(ctx) do { if ((ctx) != NULL) {talloc_free(ctx); ctx=NULL;} } while(0) +#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c new file mode 100644 index 0000000000..d0dfcb8bbf --- /dev/null +++ b/nsswitch/wb_common.c @@ -0,0 +1,690 @@ +/* + Unix SMB/CIFS implementation. + + winbind client common code + + Copyright (C) Tim Potter 2000 + Copyright (C) Andrew Tridgell 2000 + Copyright (C) Andrew Bartlett 2002 + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "winbind_client.h" + +/* Global variables. These are effectively the client state information */ + +int winbindd_fd = -1; /* fd for winbindd socket */ +static int is_privileged = 0; + +/* Free a response structure */ + +void winbindd_free_response(struct winbindd_response *response) +{ + /* Free any allocated extra_data */ + + if (response) + SAFE_FREE(response->extra_data.data); +} + +/* Initialise a request structure */ + +void winbindd_init_request(struct winbindd_request *request, int request_type) +{ + request->length = sizeof(struct winbindd_request); + + request->cmd = (enum winbindd_cmd)request_type; + request->pid = getpid(); + +} + +/* Initialise a response structure */ + +static void init_response(struct winbindd_response *response) +{ + /* Initialise return value */ + + response->result = WINBINDD_ERROR; +} + +/* Close established socket */ + +void winbind_close_sock(void) +{ + if (winbindd_fd != -1) { + close(winbindd_fd); + winbindd_fd = -1; + } +} + +#define CONNECT_TIMEOUT 30 + +/* Make sure socket handle isn't stdin, stdout or stderr */ +#define RECURSION_LIMIT 3 + +static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) +{ + int new_fd; + if (fd >= 0 && fd <= 2) { +#ifdef F_DUPFD + if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { + return -1; + } + /* Paranoia */ + if (new_fd < 3) { + close(new_fd); + return -1; + } + close(fd); + return new_fd; +#else + if (limit <= 0) + return -1; + + new_fd = dup(fd); + if (new_fd == -1) + return -1; + + /* use the program stack to hold our list of FDs to close */ + new_fd = make_nonstd_fd_internals(new_fd, limit - 1); + close(fd); + return new_fd; +#endif + } + return fd; +} + +/**************************************************************************** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY + Set close on exec also. +****************************************************************************/ + +static int make_safe_fd(int fd) +{ + int result, flags; + int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); + if (new_fd == -1) { + close(fd); + return -1; + } + + /* Socket should be nonblocking. */ +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if ((flags = fcntl(new_fd, F_GETFL)) == -1) { + close(new_fd); + return -1; + } + + flags |= FLAG_TO_SET; + if (fcntl(new_fd, F_SETFL, flags) == -1) { + close(new_fd); + return -1; + } + +#undef FLAG_TO_SET + + /* Socket should be closed on exec() */ +#ifdef FD_CLOEXEC + result = flags = fcntl(new_fd, F_GETFD, 0); + if (flags >= 0) { + flags |= FD_CLOEXEC; + result = fcntl( new_fd, F_SETFD, flags ); + } + if (result < 0) { + close(new_fd); + return -1; + } +#endif + return new_fd; +} + +/* Connect to winbindd socket */ + +static int winbind_named_pipe_sock(const char *dir) +{ + struct sockaddr_un sunaddr; + struct stat st; + char *path = NULL; + int fd; + int wait_time; + int slept; + + /* Check permissions on unix socket directory */ + + if (lstat(dir, &st) == -1) { + errno = ENOENT; + return -1; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + errno = ENOENT; + return -1; + } + + /* Connect to socket */ + + if (asprintf(&path, "%s/%s", dir, WINBINDD_SOCKET_NAME) < 0) { + return -1; + } + + ZERO_STRUCT(sunaddr); + sunaddr.sun_family = AF_UNIX; + strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if (lstat(path, &st) == -1) { + errno = ENOENT; + SAFE_FREE(path); + return -1; + } + + SAFE_FREE(path); + /* Check permissions on unix socket file */ + + if (!S_ISSOCK(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + errno = ENOENT; + return -1; + } + + /* Connect to socket */ + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return -1; + } + + /* Set socket non-blocking and close on exec. */ + + if ((fd = make_safe_fd( fd)) == -1) { + return fd; + } + + for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1; + wait_time += slept) { + struct timeval tv; + fd_set w_fds; + int ret; + int connect_errno = 0; + socklen_t errnosize; + + if (wait_time >= CONNECT_TIMEOUT) + goto error_out; + + switch (errno) { + case EINPROGRESS: + FD_ZERO(&w_fds); + FD_SET(fd, &w_fds); + tv.tv_sec = CONNECT_TIMEOUT - wait_time; + tv.tv_usec = 0; + + ret = select(fd + 1, NULL, &w_fds, NULL, &tv); + + if (ret > 0) { + errnosize = sizeof(connect_errno); + + ret = getsockopt(fd, SOL_SOCKET, + SO_ERROR, &connect_errno, &errnosize); + + if (ret >= 0 && connect_errno == 0) { + /* Connect succeed */ + goto out; + } + } + + slept = CONNECT_TIMEOUT; + break; + case EAGAIN: + slept = rand() % 3 + 1; + sleep(slept); + break; + default: + goto error_out; + } + + } + + out: + + return fd; + + error_out: + + close(fd); + return -1; +} + +static const char *winbindd_socket_dir(void) +{ +#ifdef SOCKET_WRAPPER + const char *env_dir; + + env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); + if (env_dir) { + return env_dir; + } +#endif + + return WINBINDD_SOCKET_DIR; +} + +/* Connect to winbindd socket */ + +static int winbind_open_pipe_sock(int recursing, int need_priv) +{ +#ifdef HAVE_UNIXSOCKET + static pid_t our_pid; + struct winbindd_request request; + struct winbindd_response response; + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (our_pid != getpid()) { + winbind_close_sock(); + our_pid = getpid(); + } + + if ((need_priv != 0) && (is_privileged == 0)) { + winbind_close_sock(); + } + + if (winbindd_fd != -1) { + return winbindd_fd; + } + + if (recursing) { + return -1; + } + + if ((winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir())) == -1) { + return -1; + } + + is_privileged = 0; + + /* version-check the socket */ + + request.wb_flags = WBFLAG_RECURSE; + if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { + winbind_close_sock(); + return -1; + } + + /* try and get priv pipe */ + + request.wb_flags = WBFLAG_RECURSE; + if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { + int fd; + if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) { + close(winbindd_fd); + winbindd_fd = fd; + is_privileged = 1; + } + } + + if ((need_priv != 0) && (is_privileged == 0)) { + return -1; + } + + SAFE_FREE(response.extra_data.data); + + return winbindd_fd; +#else + return -1; +#endif /* HAVE_UNIXSOCKET */ +} + +/* Write data to winbindd socket */ + +int winbind_write_sock(void *buffer, int count, int recursing, int need_priv) +{ + int result, nwritten; + + /* Open connection to winbind daemon */ + + restart: + + if (winbind_open_pipe_sock(recursing, need_priv) == -1) { + errno = ENOENT; + return -1; + } + + /* Write data to socket */ + + nwritten = 0; + + while(nwritten < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + + if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { + winbind_close_sock(); + return -1; /* Select error */ + } + + /* Write should be OK if fd not available for reading */ + + if (!FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the write */ + + result = write(winbindd_fd, + (char *)buffer + nwritten, + count - nwritten); + + if ((result == -1) || (result == 0)) { + + /* Write failed */ + + winbind_close_sock(); + return -1; + } + + nwritten += result; + + } else { + + /* Pipe has closed on remote end */ + + winbind_close_sock(); + goto restart; + } + } + + return nwritten; +} + +/* Read data from winbindd socket */ + +int winbind_read_sock(void *buffer, int count) +{ + int nread = 0; + int total_time = 0, selret; + + if (winbindd_fd == -1) { + return -1; + } + + /* Read data from socket */ + while(nread < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + /* Wait for 5 seconds for a reply. May need to parameterise this... */ + tv.tv_sec = 5; + + if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) { + winbind_close_sock(); + return -1; /* Select error */ + } + + if (selret == 0) { + /* Not ready for read yet... */ + if (total_time >= 30) { + /* Timeout */ + winbind_close_sock(); + return -1; + } + total_time += 5; + continue; + } + + if (FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the Read */ + + int result = read(winbindd_fd, (char *)buffer + nread, + count - nread); + + if ((result == -1) || (result == 0)) { + + /* Read failed. I think the only useful thing we + can do here is just return -1 and fail since the + transaction has failed half way through. */ + + winbind_close_sock(); + return -1; + } + + nread += result; + + } + } + + return nread; +} + +/* Read reply */ + +int winbindd_read_reply(struct winbindd_response *response) +{ + int result1, result2 = 0; + + if (!response) { + return -1; + } + + /* Read fixed length response */ + + result1 = winbind_read_sock(response, + sizeof(struct winbindd_response)); + if (result1 == -1) { + return -1; + } + + /* We actually send the pointer value of the extra_data field from + the server. This has no meaning in the client's address space + so we clear it out. */ + + response->extra_data.data = NULL; + + /* Read variable length response */ + + if (response->length > sizeof(struct winbindd_response)) { + int extra_data_len = response->length - + sizeof(struct winbindd_response); + + /* Mallocate memory for extra data */ + + if (!(response->extra_data.data = malloc(extra_data_len))) { + return -1; + } + + result2 = winbind_read_sock(response->extra_data.data, + extra_data_len); + if (result2 == -1) { + winbindd_free_response(response); + return -1; + } + } + + /* Return total amount of data read */ + + return result1 + result2; +} + +/* + * send simple types of requests + */ + +NSS_STATUS winbindd_send_request(int req_type, int need_priv, + struct winbindd_request *request) +{ + struct winbindd_request lrequest; + + /* Check for our tricky environment variable */ + + if (winbind_env_set()) { + return NSS_STATUS_NOTFOUND; + } + + if (!request) { + ZERO_STRUCT(lrequest); + request = &lrequest; + } + + /* Fill in request and send down pipe */ + + winbindd_init_request(request, req_type); + + if (winbind_write_sock(request, sizeof(*request), + request->wb_flags & WBFLAG_RECURSE, + need_priv) == -1) + { + /* Set ENOENT for consistency. Required by some apps */ + errno = ENOENT; + + return NSS_STATUS_UNAVAIL; + } + + if ((request->extra_len != 0) && + (winbind_write_sock(request->extra_data.data, + request->extra_len, + request->wb_flags & WBFLAG_RECURSE, + need_priv) == -1)) + { + /* Set ENOENT for consistency. Required by some apps */ + errno = ENOENT; + + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +/* + * Get results from winbindd request + */ + +NSS_STATUS winbindd_get_response(struct winbindd_response *response) +{ + struct winbindd_response lresponse; + + if (!response) { + ZERO_STRUCT(lresponse); + response = &lresponse; + } + + init_response(response); + + /* Wait for reply */ + if (winbindd_read_reply(response) == -1) { + /* Set ENOENT for consistency. Required by some apps */ + errno = ENOENT; + + return NSS_STATUS_UNAVAIL; + } + + /* Throw away extra data if client didn't request it */ + if (response == &lresponse) { + winbindd_free_response(response); + } + + /* Copy reply data from socket */ + if (response->result != WINBINDD_OK) { + return NSS_STATUS_NOTFOUND; + } + + return NSS_STATUS_SUCCESS; +} + +/* Handle simple types of requests */ + +NSS_STATUS winbindd_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status = NSS_STATUS_UNAVAIL; + int count = 0; + + while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { + status = winbindd_send_request(req_type, 0, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + status = winbindd_get_response(response); + count += 1; + } + + return status; +} + +NSS_STATUS winbindd_priv_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status = NSS_STATUS_UNAVAIL; + int count = 0; + + while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { + status = winbindd_send_request(req_type, 1, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + status = winbindd_get_response(response); + count += 1; + } + + return status; +} + +/************************************************************************* + ************************************************************************/ + +const char *nss_err_str(NSS_STATUS ret) +{ + switch (ret) { + case NSS_STATUS_TRYAGAIN: + return "NSS_STATUS_TRYAGAIN"; + case NSS_STATUS_SUCCESS: + return "NSS_STATUS_SUCCESS"; + case NSS_STATUS_NOTFOUND: + return "NSS_STATUS_NOTFOUND"; + case NSS_STATUS_UNAVAIL: + return "NSS_STATUS_UNAVAIL"; +#ifdef NSS_STATUS_RETURN + case NSS_STATUS_RETURN: + return "NSS_STATUS_RETURN"; +#endif + default: + return "UNKNOWN RETURN CODE!!!!!!!"; + } +} diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c new file mode 100644 index 0000000000..36c2818ccf --- /dev/null +++ b/nsswitch/wbinfo.c @@ -0,0 +1,1984 @@ +/* + Unix SMB/CIFS implementation. + + Winbind status program. + + Copyright (C) Tim Potter 2000-2003 + 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 3 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, see . +*/ + +#include "includes.h" +#include "winbind_client.h" +#include "libwbclient/wbclient.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +static struct wbcInterfaceDetails *init_interface_details(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + static struct wbcInterfaceDetails *details; + + if (details) { + return details; + } + + wbc_status = wbcInterfaceDetails(&details); + if (!WBC_ERROR_IS_OK(wbc_status)) { + d_fprintf(stderr, "could not obtain winbind interface details!\n"); + } + + return details; +} + +static char winbind_separator_int(bool strict) +{ + struct wbcInterfaceDetails *details; + static bool got_sep; + static char sep; + + if (got_sep) + return sep; + + details = init_interface_details(); + + if (!details) { + d_fprintf(stderr, "could not obtain winbind separator!\n"); + if (strict) { + return 0; + } + /* HACK: (this module should not call lp_ funtions) */ + return *lp_winbind_separator(); + } + + sep = details->winbind_separator; + got_sep = true; + + if (!sep) { + d_fprintf(stderr, "winbind separator was NULL!\n"); + if (strict) { + return 0; + } + /* HACK: (this module should not call lp_ funtions) */ + sep = *lp_winbind_separator(); + } + + return sep; +} + +static char winbind_separator(void) +{ + return winbind_separator_int(false); +} + +static const char *get_winbind_domain(void) +{ + static struct wbcInterfaceDetails *details; + + details = init_interface_details(); + + if (!details) { + d_fprintf(stderr, "could not obtain winbind domain name!\n"); + + /* HACK: (this module should not call lp_ functions) */ + return lp_workgroup(); + } + + return details->netbios_domain; +} + +/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the + form DOMAIN/user into a domain and a user */ + +static bool parse_wbinfo_domain_user(const char *domuser, fstring domain, + fstring user) +{ + + char *p = strchr(domuser,winbind_separator()); + + if (!p) { + /* Maybe it was a UPN? */ + if ((p = strchr(domuser, '@')) != NULL) { + fstrcpy(domain, ""); + fstrcpy(user, domuser); + return true; + } + + fstrcpy(user, domuser); + fstrcpy(domain, get_winbind_domain()); + return true; + } + + fstrcpy(user, p+1); + fstrcpy(domain, domuser); + domain[PTR_DIFF(p, domuser)] = 0; + strupper_m(domain); + + return true; +} + +/* Parse string of "uid,sid" or "gid,sid" into separate int and string values. + * Return true if input was valid, false otherwise. */ +static bool parse_mapping_arg(char *arg, int *id, char **sid) +{ + char *tmp, *endptr; + + if (!arg || !*arg) + return false; + + tmp = strtok(arg, ","); + *sid = strtok(NULL, ","); + + if (!tmp || !*tmp || !*sid || !**sid) + return false; + + /* Because atoi() can return 0 on invalid input, which would be a valid + * UID/GID we must use strtoul() and do error checking */ + *id = strtoul(tmp, &endptr, 10); + + if (endptr[0] != '\0') + return false; + + return true; +} + +/* pull pwent info for a given user */ + +static bool wbinfo_get_userinfo(char *user) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct passwd *pwd = NULL; + + wbc_status = wbcGetpwnam(user, &pwd); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + d_printf("%s:%s:%d:%d:%s:%s:%s\n", + pwd->pw_name, + pwd->pw_passwd, + pwd->pw_uid, + pwd->pw_gid, + pwd->pw_gecos, + pwd->pw_dir, + pwd->pw_shell); + + return true; +} + +/* pull pwent info for a given uid */ +static bool wbinfo_get_uidinfo(int uid) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct passwd *pwd = NULL; + + wbc_status = wbcGetpwuid(uid, &pwd); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + d_printf("%s:%s:%d:%d:%s:%s:%s\n", + pwd->pw_name, + pwd->pw_passwd, + pwd->pw_uid, + pwd->pw_gid, + pwd->pw_gecos, + pwd->pw_dir, + pwd->pw_shell); + + return true; +} + +/* pull grent for a given group */ +static bool wbinfo_get_groupinfo(const char *group) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct group *grp; + + wbc_status = wbcGetgrnam(group, &grp); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + d_printf("%s:%s:%d\n", + grp->gr_name, + grp->gr_passwd, + grp->gr_gid); + + wbcFreeMemory(grp); + + return true; +} + +/* List groups a user is a member of */ + +static bool wbinfo_get_usergroups(const char *user) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uint32_t num_groups; + uint32_t i; + gid_t *groups = NULL; + + /* Send request */ + + wbc_status = wbcGetGroups(user, &num_groups, &groups); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + for (i = 0; i < num_groups; i++) { + d_printf("%d\n", (int)groups[i]); + } + + wbcFreeMemory(groups); + + return true; +} + + +/* List group SIDs a user SID is a member of */ +static bool wbinfo_get_usersids(const char *user_sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uint32_t num_sids; + uint32_t i; + struct wbcDomainSid user_sid, *sids = NULL; + + /* Send request */ + + wbc_status = wbcStringToSid(user_sid_str, &user_sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcLookupUserSids(&user_sid, false, &num_sids, &sids); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + for (i = 0; i < num_sids; i++) { + char *str = NULL; + wbc_status = wbcSidToString(&sids[i], &str); + if (!WBC_ERROR_IS_OK(wbc_status)) { + wbcFreeMemory(sids); + return false; + } + d_printf("%s\n", str); + wbcFreeMemory(str); + } + + wbcFreeMemory(sids); + + return true; +} + +static bool wbinfo_get_userdomgroups(const char *user_sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uint32_t num_sids; + uint32_t i; + struct wbcDomainSid user_sid, *sids = NULL; + + /* Send request */ + + wbc_status = wbcStringToSid(user_sid_str, &user_sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcLookupUserSids(&user_sid, true, &num_sids, &sids); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + for (i = 0; i < num_sids; i++) { + char *str = NULL; + wbc_status = wbcSidToString(&sids[i], &str); + if (!WBC_ERROR_IS_OK(wbc_status)) { + wbcFreeMemory(sids); + return false; + } + d_printf("%s\n", str); + wbcFreeMemory(str); + } + + wbcFreeMemory(sids); + + return true; +} + +/* Convert NetBIOS name to IP */ + +static bool wbinfo_wins_byname(const char *name) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *ip = NULL; + + wbc_status = wbcResolveWinsByName(name, &ip); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%s\n", ip); + + wbcFreeMemory(ip); + + return true; +} + +/* Convert IP to NetBIOS name */ + +static bool wbinfo_wins_byip(const char *ip) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + char *name = NULL; + + wbc_status = wbcResolveWinsByIP(ip, &name); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%s\n", name); + + wbcFreeMemory(name); + + return true; +} + +/* List all/trusted domains */ + +static bool wbinfo_list_domains(bool list_all_domains, bool verbose) +{ + struct wbcDomainInfo *domain_list = NULL; + size_t num_domains; + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + bool print_all = !list_all_domains && verbose; + int i; + + wbc_status = wbcListTrusts(&domain_list, &num_domains); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + if (print_all) { + d_printf("%-16s%-24s%-12s%-12s%-5s%-5s\n", + "Domain Name", "DNS Domain", "Trust Type", + "Transitive", "In", "Out"); + } + + for (i=0; isid, &sid_str); + if (!WBC_ERROR_IS_OK(wbc_status)) { + wbcFreeMemory(dinfo); + return false; + } + + /* Display response */ + + d_printf("Name : %s\n", dinfo->short_name); + d_printf("Alt_Name : %s\n", dinfo->dns_name); + + d_printf("SID : %s\n", sid_str); + + d_printf("Active Directory : %s\n", + (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_AD) ? "Yes" : "No"); + d_printf("Native : %s\n", + (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ? "Yes" : "No"); + + d_printf("Primary : %s\n", + (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ? "Yes" : "No"); + + wbcFreeMemory(sid_str); + wbcFreeMemory(dinfo); + + return true; +} + +/* Get a foreign DC's name */ +static bool wbinfo_getdcname(const char *domain_name) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.domain_name, domain_name); + + /* Send request */ + + if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) != + NSS_STATUS_SUCCESS) { + d_fprintf(stderr, "Could not get dc name for %s\n", domain_name); + return false; + } + + /* Display response */ + + d_printf("%s\n", response.data.dc_name); + + return true; +} + +/* Find a DC */ +static bool wbinfo_dsgetdcname(const char *domain_name, uint32_t flags) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.data.dsgetdcname.domain_name, domain_name); + request.data.dsgetdcname.flags = flags; + + request.flags |= DS_DIRECTORY_SERVICE_REQUIRED; + + /* Send request */ + + if (winbindd_request_response(WINBINDD_DSGETDCNAME, &request, &response) != + NSS_STATUS_SUCCESS) { + d_fprintf(stderr, "Could not find dc for %s\n", domain_name); + return false; + } + + /* Display response */ + + d_printf("%s\n", response.data.dsgetdcname.dc_unc); + d_printf("%s\n", response.data.dsgetdcname.dc_address); + d_printf("%d\n", response.data.dsgetdcname.dc_address_type); + d_printf("%s\n", response.data.dsgetdcname.domain_guid); + d_printf("%s\n", response.data.dsgetdcname.domain_name); + d_printf("%s\n", response.data.dsgetdcname.forest_name); + d_printf("0x%08x\n", response.data.dsgetdcname.dc_flags); + d_printf("%s\n", response.data.dsgetdcname.dc_site_name); + d_printf("%s\n", response.data.dsgetdcname.client_site_name); + + return true; +} + +/* Check trust account password */ + +static bool wbinfo_check_secret(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcAuthErrorInfo *error = NULL; + + wbc_status = wbcCheckTrustCredentials(NULL, &error); + + d_printf("checking the trust secret via RPC calls %s\n", + WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); + + if (wbc_status == WBC_ERR_AUTH_ERROR) { + d_fprintf(stderr, "error code was %s (0x%x)\n", + error->nt_string, error->nt_status); + wbcFreeMemory(error); + } + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + return true; +} + +/* Convert uid to sid */ + +static bool wbinfo_uid_to_sid(uid_t uid) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + char *sid_str = NULL; + + /* Send request */ + + wbc_status = wbcUidToSid(uid, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcSidToString(&sid, &sid_str); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%s\n", sid_str); + + wbcFreeMemory(sid_str); + + return true; +} + +/* Convert gid to sid */ + +static bool wbinfo_gid_to_sid(gid_t gid) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + char *sid_str = NULL; + + /* Send request */ + + wbc_status = wbcGidToSid(gid, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcSidToString(&sid, &sid_str); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%s\n", sid_str); + + wbcFreeMemory(sid_str); + + return true; +} + +/* Convert sid to uid */ + +static bool wbinfo_sid_to_uid(const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + uid_t uid; + + /* Send request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcSidToUid(&sid, &uid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%d\n", (int)uid); + + return true; +} + +static bool wbinfo_sid_to_gid(const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + gid_t gid; + + /* Send request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcSidToGid(&sid, &gid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%d\n", (int)gid); + + return true; +} + +static bool wbinfo_allocate_uid(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uid_t uid; + + /* Send request */ + + wbc_status = wbcAllocateUid(&uid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("New uid: %d\n", uid); + + return true; +} + +static bool wbinfo_allocate_gid(void) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + gid_t gid; + + /* Send request */ + + wbc_status = wbcAllocateGid(&gid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("New gid: %d\n", gid); + + return true; +} + +static bool wbinfo_set_uid_mapping(uid_t uid, const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + + /* Send request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcSetUidMapping(uid, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("uid %d now mapped to sid %s\n", uid, sid_str); + + return true; +} + +static bool wbinfo_set_gid_mapping(gid_t gid, const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + + /* Send request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcSetGidMapping(gid, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("gid %d now mapped to sid %s\n", gid, sid_str); + + return true; +} + +static bool wbinfo_remove_uid_mapping(uid_t uid, const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + + /* Send request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcRemoveUidMapping(uid, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("Removed uid %d to sid %s mapping\n", uid, sid_str); + + return true; +} + +static bool wbinfo_remove_gid_mapping(gid_t gid, const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + + /* Send request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcRemoveGidMapping(gid, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("Removed gid %d to sid %s mapping\n", gid, sid_str); + + return true; +} + +/* Convert sid to string */ + +static bool wbinfo_lookupsid(const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + char *domain; + char *name; + enum wbcSidType type; + + /* Send off request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcLookupSid(&sid, &domain, &name, &type); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%s%c%s %d\n", + domain, winbind_separator(), name, type); + + return true; +} + +/* Convert sid to fullname */ + +static bool wbinfo_lookupsid_fullname(const char *sid_str) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainSid sid; + char *domain; + char *name; + enum wbcSidType type; + + /* Send off request */ + + wbc_status = wbcStringToSid(sid_str, &sid); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + wbc_status = wbcGetDisplayName(&sid, &domain, &name, &type); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + /* Display response */ + + d_printf("%s%c%s %d\n", + domain, winbind_separator(), name, type); + + return true; +} + +/* Lookup a list of RIDs */ + +static bool wbinfo_lookuprids(const char *domain, const char *arg) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + struct wbcDomainInfo *dinfo = NULL; + char *domain_name = NULL; + const char **names = NULL; + enum wbcSidType *types = NULL; + size_t i; + int num_rids; + uint32 *rids = NULL; + const char *p; + char *ridstr; + TALLOC_CTX *mem_ctx = NULL; + bool ret = false; + + if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) { + domain = get_winbind_domain(); + } + + /* Send request */ + + wbc_status = wbcDomainInfo(domain, &dinfo); + if (!WBC_ERROR_IS_OK(wbc_status)) { + d_printf("wbcDomainInfo(%s) failed: %s\n", domain, + wbcErrorString(wbc_status)); + goto done; + } + + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + d_printf("talloc_new failed\n"); + goto done; + } + + num_rids = 0; + rids = NULL; + p = arg; + + while (next_token_talloc(mem_ctx, &p, &ridstr, " ,\n")) { + uint32 rid = strtoul(ridstr, NULL, 10); + ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids); + } + + if (rids == NULL) { + d_printf("no rids\n"); + goto done; + } + + wbc_status = wbcLookupRids(&dinfo->sid, num_rids, rids, + (const char **)&domain_name, &names, &types); + if (!WBC_ERROR_IS_OK(wbc_status)) { + d_printf("winbind_lookup_rids failed: %s\n", + wbcErrorString(wbc_status)); + goto done; + } + + d_printf("Domain: %s\n", domain_name); + + for (i=0; int_string, + err->nt_status, + err->display_string); + wbcFreeMemory(err); + } else if (WBC_ERROR_IS_OK(wbc_status)) { + wbcFreeMemory(info); + } + + data_blob_free(&nt); + data_blob_free(&lm); + SAFE_FREE(pass); + + return WBC_ERROR_IS_OK(wbc_status); +} + +/* Authenticate a user with a plaintext password and set a token */ + +static bool wbinfo_klog(char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + char *p; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + p = strchr(username, '%'); + + if (p) { + *p = 0; + fstrcpy(request.data.auth.user, username); + fstrcpy(request.data.auth.pass, p + 1); + *p = '%'; + } else { + fstrcpy(request.data.auth.user, username); + fstrcpy(request.data.auth.pass, getpass("Password: ")); + } + + request.flags |= WBFLAG_PAM_AFS_TOKEN; + + result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); + + /* Display response */ + + d_printf("plaintext password authentication %s\n", + (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); + + if (response.data.auth.nt_status) + d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", + response.data.auth.nt_status_string, + response.data.auth.nt_status, + response.data.auth.error_string); + + if (result != NSS_STATUS_SUCCESS) + return false; + + if (response.extra_data.data == NULL) { + d_fprintf(stderr, "Did not get token data\n"); + return false; + } + + if (!afs_settoken_str((char *)response.extra_data.data)) { + d_fprintf(stderr, "Could not set token\n"); + return false; + } + + d_printf("Successfully created AFS token\n"); + return true; +} + +/* Print domain users */ + +static bool print_domain_users(const char *domain) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uint32_t i; + uint32_t num_users = 0; + const char **users = NULL; + + /* Send request to winbind daemon */ + + /* '.' is the special sign for our own domain */ + if (domain && strcmp(domain, ".") == 0) { + domain = get_winbind_domain(); + } + + wbc_status = wbcListUsers(domain, &num_users, &users); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + for (i=0; i < num_users; i++) { + d_printf("%s\n", users[i]); + } + + wbcFreeMemory(users); + + return true; +} + +/* Print domain groups */ + +static bool print_domain_groups(const char *domain) +{ + wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; + uint32_t i; + uint32_t num_groups = 0; + const char **groups = NULL; + + /* Send request to winbind daemon */ + + /* '.' is the special sign for our own domain */ + if (domain && strcmp(domain, ".") == 0) { + domain = get_winbind_domain(); + } + + wbc_status = wbcListGroups(domain, &num_groups, &groups); + if (!WBC_ERROR_IS_OK(wbc_status)) { + return false; + } + + for (i=0; i < num_groups; i++) { + d_printf("%s\n", groups[i]); + } + + wbcFreeMemory(groups); + + return true; +} + +/* Set the authorised user for winbindd access in secrets.tdb */ + +static bool wbinfo_set_auth_user(char *username) +{ + const char *password; + char *p; + fstring user, domain; + + /* Separate into user and password */ + + parse_wbinfo_domain_user(username, domain, user); + + p = strchr(user, '%'); + + if (p != NULL) { + *p = 0; + password = p+1; + } else { + char *thepass = getpass("Password: "); + if (thepass) { + password = thepass; + } else + password = ""; + } + + /* Store or remove DOMAIN\username%password in secrets.tdb */ + + secrets_init(); + + if (user[0]) { + + if (!secrets_store(SECRETS_AUTH_USER, user, + strlen(user) + 1)) { + d_fprintf(stderr, "error storing username\n"); + return false; + } + + /* We always have a domain name added by the + parse_wbinfo_domain_user() function. */ + + if (!secrets_store(SECRETS_AUTH_DOMAIN, domain, + strlen(domain) + 1)) { + d_fprintf(stderr, "error storing domain name\n"); + return false; + } + + } else { + secrets_delete(SECRETS_AUTH_USER); + secrets_delete(SECRETS_AUTH_DOMAIN); + } + + if (password[0]) { + + if (!secrets_store(SECRETS_AUTH_PASSWORD, password, + strlen(password) + 1)) { + d_fprintf(stderr, "error storing password\n"); + return false; + } + + } else + secrets_delete(SECRETS_AUTH_PASSWORD); + + return true; +} + +static void wbinfo_get_auth_user(void) +{ + char *user, *domain, *password; + + /* Lift data from secrets file */ + + secrets_fetch_ipc_userpass(&user, &domain, &password); + + if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){ + + SAFE_FREE(user); + SAFE_FREE(domain); + SAFE_FREE(password); + d_printf("No authorised user configured\n"); + return; + } + + /* Pretty print authorised user info */ + + d_printf("%s%s%s%s%s\n", domain ? domain : "", domain ? lp_winbind_separator(): "", + user, password ? "%" : "", password ? password : ""); + + SAFE_FREE(user); + SAFE_FREE(domain); + SAFE_FREE(password); +} + +static bool wbinfo_ping(void) +{ + wbcErr wbc_status; + + wbc_status = wbcPing(); + + /* Display response */ + + d_printf("Ping to winbindd %s\n", + WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); + + return WBC_ERROR_IS_OK(wbc_status); +} + +static bool wbinfo_change_user_password(const char *username) +{ + wbcErr wbc_status; + char *old_password = NULL; + char *new_password = NULL; + + old_password = wbinfo_prompt_pass("old", username); + new_password = wbinfo_prompt_pass("new", username); + + wbc_status = wbcChangeUserPassword(username, old_password, new_password); + + /* Display response */ + + d_printf("Password change for user %s %s\n", username, + WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); + + SAFE_FREE(old_password); + SAFE_FREE(new_password); + + return WBC_ERROR_IS_OK(wbc_status); +} + +/* Main program */ + +enum { + OPT_SET_AUTH_USER = 1000, + OPT_GET_AUTH_USER, + OPT_DOMAIN_NAME, + OPT_SEQUENCE, + OPT_GETDCNAME, + OPT_DSGETDCNAME, + OPT_USERDOMGROUPS, + OPT_USERSIDS, + OPT_ALLOCATE_UID, + OPT_ALLOCATE_GID, + OPT_SET_UID_MAPPING, + OPT_SET_GID_MAPPING, + OPT_REMOVE_UID_MAPPING, + OPT_REMOVE_GID_MAPPING, + OPT_SEPARATOR, + OPT_LIST_ALL_DOMAINS, + OPT_LIST_OWN_DOMAIN, + OPT_UID_INFO, + OPT_GROUP_INFO, + OPT_VERBOSE, + OPT_ONLINESTATUS, + OPT_CHANGE_USER_PASSWORD, + OPT_SID_TO_FULLNAME +}; + +int main(int argc, char **argv, char **envp) +{ + int opt; + TALLOC_CTX *frame = talloc_stackframe(); + poptContext pc; + static char *string_arg; + char *string_subarg = NULL; + static char *opt_domain_name; + static int int_arg; + int int_subarg = -1; + int result = 1; + bool verbose = false; + + struct poptOption long_options[] = { + POPT_AUTOHELP + + /* longName, shortName, argInfo, argPtr, value, descrip, + argDesc */ + + { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"}, + { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" }, + { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" }, + { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" }, + { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, + { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, + { "sid-to-fullname", 0, POPT_ARG_STRING, &string_arg, + OPT_SID_TO_FULLNAME, "Converts sid to fullname", "SID" }, + { "lookup-rids", 'R', POPT_ARG_STRING, &string_arg, 'R', "Converts RIDs to names", "RIDs" }, + { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, + { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, + { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, + { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, + { "allocate-uid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_UID, + "Get a new UID out of idmap" }, + { "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID, + "Get a new GID out of idmap" }, + { "set-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_SET_UID_MAPPING, "Create or modify uid to sid mapping in idmap", "UID,SID" }, + { "set-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_SET_GID_MAPPING, "Create or modify gid to sid mapping in idmap", "GID,SID" }, + { "remove-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_UID_MAPPING, "Remove uid to sid mapping in idmap", "UID,SID" }, + { "remove-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_GID_MAPPING, "Remove gid to sid mapping in idmap", "GID,SID" }, + { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" }, + { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" }, + { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" }, + { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" }, + { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" }, + { "online-status", 0, POPT_ARG_NONE, 0, OPT_ONLINESTATUS, "Show whether domains are marked as online or offline"}, + { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" }, + { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" }, + { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" }, + { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" }, + { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, + { "user-domgroups", 0, POPT_ARG_STRING, &string_arg, + OPT_USERDOMGROUPS, "Get user domain groups", "SID" }, + { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" }, + { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, + { "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, + { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME, + "Get a DC name for a foreign domain", "domainname" }, + { "dsgetdcname", 0, POPT_ARG_STRING, &string_arg, OPT_DSGETDCNAME, "Find a DC for a domain", "domainname" }, + { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, + { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, + { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" }, +#ifdef WITH_FAKE_KASERVER + { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" }, +#endif +#ifdef HAVE_KRB5 + { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" }, + /* destroys wbinfo --help output */ + /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */ +#endif + { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL }, + { "verbose", 0, POPT_ARG_NONE, 0, OPT_VERBOSE, "Print additional information per command", NULL }, + { "change-user-password", 0, POPT_ARG_STRING, &string_arg, OPT_CHANGE_USER_PASSWORD, "Change the password for a user", NULL }, + POPT_COMMON_CONFIGFILE + POPT_COMMON_VERSION + POPT_TABLEEND + }; + + /* Samba client initialisation */ + load_case_tables(); + + + /* Parse options */ + + pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0); + + /* Parse command line options */ + + if (argc == 1) { + poptPrintHelp(pc, stderr, 0); + return 1; + } + + while((opt = poptGetNextOpt(pc)) != -1) { + /* get the generic configuration parameters like --domain */ + switch (opt) { + case OPT_VERBOSE: + verbose = True; + break; + } + } + + poptFreeContext(pc); + + if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, true)) { + d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n", + get_dyn_CONFIGFILE(), strerror(errno)); + exit(1); + } + + if (!init_names()) + return 1; + + load_interfaces(); + + pc = poptGetContext(NULL, argc, (const char **)argv, long_options, + POPT_CONTEXT_KEEP_FIRST); + + while((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 'u': + if (!print_domain_users(opt_domain_name)) { + d_fprintf(stderr, "Error looking up domain users\n"); + goto done; + } + break; + case 'g': + if (!print_domain_groups(opt_domain_name)) { + d_fprintf(stderr, "Error looking up domain groups\n"); + goto done; + } + break; + case 's': + if (!wbinfo_lookupsid(string_arg)) { + d_fprintf(stderr, "Could not lookup sid %s\n", string_arg); + goto done; + } + break; + case OPT_SID_TO_FULLNAME: + if (!wbinfo_lookupsid_fullname(string_arg)) { + d_fprintf(stderr, "Could not lookup sid %s\n", + string_arg); + goto done; + } + break; + case 'R': + if (!wbinfo_lookuprids(opt_domain_name, string_arg)) { + d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg); + goto done; + } + break; + case 'n': + if (!wbinfo_lookupname(string_arg)) { + d_fprintf(stderr, "Could not lookup name %s\n", string_arg); + goto done; + } + break; + case 'N': + if (!wbinfo_wins_byname(string_arg)) { + d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg); + goto done; + } + break; + case 'I': + if (!wbinfo_wins_byip(string_arg)) { + d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg); + goto done; + } + break; + case 'U': + if (!wbinfo_uid_to_sid(int_arg)) { + d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg); + goto done; + } + break; + case 'G': + if (!wbinfo_gid_to_sid(int_arg)) { + d_fprintf(stderr, "Could not convert gid %d to sid\n", + int_arg); + goto done; + } + break; + case 'S': + if (!wbinfo_sid_to_uid(string_arg)) { + d_fprintf(stderr, "Could not convert sid %s to uid\n", + string_arg); + goto done; + } + break; + case 'Y': + if (!wbinfo_sid_to_gid(string_arg)) { + d_fprintf(stderr, "Could not convert sid %s to gid\n", + string_arg); + goto done; + } + break; + case OPT_ALLOCATE_UID: + if (!wbinfo_allocate_uid()) { + d_fprintf(stderr, "Could not allocate a uid\n"); + goto done; + } + break; + case OPT_ALLOCATE_GID: + if (!wbinfo_allocate_gid()) { + d_fprintf(stderr, "Could not allocate a gid\n"); + goto done; + } + break; + case OPT_SET_UID_MAPPING: + if (!parse_mapping_arg(string_arg, &int_subarg, + &string_subarg) || + !wbinfo_set_uid_mapping(int_subarg, string_subarg)) + { + d_fprintf(stderr, "Could not create or modify " + "uid to sid mapping\n"); + goto done; + } + break; + case OPT_SET_GID_MAPPING: + if (!parse_mapping_arg(string_arg, &int_subarg, + &string_subarg) || + !wbinfo_set_gid_mapping(int_subarg, string_subarg)) + { + d_fprintf(stderr, "Could not create or modify " + "gid to sid mapping\n"); + goto done; + } + break; + case OPT_REMOVE_UID_MAPPING: + if (!parse_mapping_arg(string_arg, &int_subarg, + &string_subarg) || + !wbinfo_remove_uid_mapping(int_subarg, + string_subarg)) + { + d_fprintf(stderr, "Could not remove uid to sid " + "mapping\n"); + goto done; + } + break; + case OPT_REMOVE_GID_MAPPING: + if (!parse_mapping_arg(string_arg, &int_subarg, + &string_subarg) || + !wbinfo_remove_gid_mapping(int_subarg, + string_subarg)) + { + d_fprintf(stderr, "Could not remove gid to sid " + "mapping\n"); + goto done; + } + break; + case 't': + if (!wbinfo_check_secret()) { + d_fprintf(stderr, "Could not check secret\n"); + goto done; + } + break; + case 'm': + if (!wbinfo_list_domains(false, verbose)) { + d_fprintf(stderr, "Could not list trusted domains\n"); + goto done; + } + break; + case OPT_SEQUENCE: + if (!wbinfo_show_sequence(opt_domain_name)) { + d_fprintf(stderr, "Could not show sequence numbers\n"); + goto done; + } + break; + case OPT_ONLINESTATUS: + if (!wbinfo_show_onlinestatus(opt_domain_name)) { + d_fprintf(stderr, "Could not show online-status\n"); + goto done; + } + break; + case 'D': + if (!wbinfo_domain_info(string_arg)) { + d_fprintf(stderr, "Could not get domain info\n"); + goto done; + } + break; + case 'i': + if (!wbinfo_get_userinfo(string_arg)) { + d_fprintf(stderr, "Could not get info for user %s\n", + string_arg); + goto done; + } + break; + case OPT_UID_INFO: + if ( !wbinfo_get_uidinfo(int_arg)) { + d_fprintf(stderr, "Could not get info for uid " + "%d\n", int_arg); + goto done; + } + break; + case OPT_GROUP_INFO: + if ( !wbinfo_get_groupinfo(string_arg)) { + d_fprintf(stderr, "Could not get info for " + "group %s\n", string_arg); + goto done; + } + break; + case 'r': + if (!wbinfo_get_usergroups(string_arg)) { + d_fprintf(stderr, "Could not get groups for user %s\n", + string_arg); + goto done; + } + break; + case OPT_USERSIDS: + if (!wbinfo_get_usersids(string_arg)) { + d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", + string_arg); + goto done; + } + break; + case OPT_USERDOMGROUPS: + if (!wbinfo_get_userdomgroups(string_arg)) { + d_fprintf(stderr, "Could not get user's domain groups " + "for user SID %s\n", string_arg); + goto done; + } + break; + case 'a': { + bool got_error = false; + + if (!wbinfo_auth(string_arg)) { + d_fprintf(stderr, "Could not authenticate user %s with " + "plaintext password\n", string_arg); + got_error = true; + } + + if (!wbinfo_auth_crap(string_arg)) { + d_fprintf(stderr, "Could not authenticate user %s with " + "challenge/response\n", string_arg); + got_error = true; + } + + if (got_error) + goto done; + break; + } + case 'K': { + uint32 flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CACHED_LOGIN | + WBFLAG_PAM_FALLBACK_AFTER_KRB5 | + WBFLAG_PAM_INFO3_TEXT; + + if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) { + d_fprintf(stderr, "Could not authenticate user [%s] with " + "Kerberos (ccache: %s)\n", string_arg, "FILE"); + goto done; + } + break; + } + case 'k': + if (!wbinfo_klog(string_arg)) { + d_fprintf(stderr, "Could not klog user\n"); + goto done; + } + break; + case 'p': + if (!wbinfo_ping()) { + d_fprintf(stderr, "could not ping winbindd!\n"); + goto done; + } + break; + case OPT_SET_AUTH_USER: + if (!wbinfo_set_auth_user(string_arg)) { + goto done; + } + break; + case OPT_GET_AUTH_USER: + wbinfo_get_auth_user(); + break; + case OPT_GETDCNAME: + if (!wbinfo_getdcname(string_arg)) { + goto done; + } + break; + case OPT_DSGETDCNAME: + if (!wbinfo_dsgetdcname(string_arg, 0)) { + goto done; + } + break; + case OPT_SEPARATOR: { + const char sep = winbind_separator_int(true); + if ( !sep ) { + goto done; + } + d_printf("%c\n", sep); + break; + } + case OPT_LIST_ALL_DOMAINS: + if (!wbinfo_list_domains(true, verbose)) { + goto done; + } + break; + case OPT_LIST_OWN_DOMAIN: + if (!wbinfo_list_own_domain()) { + goto done; + } + break; + case OPT_CHANGE_USER_PASSWORD: + if (!wbinfo_change_user_password(string_arg)) { + d_fprintf(stderr, "Could not change user password " + "for user %s\n", string_arg); + goto done; + } + break; + + /* generic configuration options */ + case OPT_DOMAIN_NAME: + break; + case OPT_VERBOSE: + break; + default: + d_fprintf(stderr, "Invalid option\n"); + poptPrintHelp(pc, stderr, 0); + goto done; + } + } + + result = 0; + + /* Exit code */ + + done: + talloc_destroy(frame); + + poptFreeContext(pc); + return result; +} diff --git a/nsswitch/winbind_client.h b/nsswitch/winbind_client.h new file mode 100644 index 0000000000..b004d9c2c0 --- /dev/null +++ b/nsswitch/winbind_client.h @@ -0,0 +1,30 @@ +#include "winbind_nss_config.h" +#include "winbind_struct_protocol.h" + +void winbindd_init_request(struct winbindd_request *req,int rq_type); +void winbindd_free_response(struct winbindd_response *response); +NSS_STATUS winbindd_send_request(int req_type, int need_priv, + struct winbindd_request *request); +NSS_STATUS winbindd_get_response(struct winbindd_response *response); +NSS_STATUS winbindd_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); +NSS_STATUS winbindd_priv_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response); +int winbindd_read_reply(struct winbindd_response *response); + +#define winbind_env_set() \ + (strcmp(getenv(WINBINDD_DONT_ENV)?getenv(WINBINDD_DONT_ENV):"0","1") == 0) + +#define winbind_off() \ + (setenv(WINBINDD_DONT_ENV, "1", 1) == 0) + +#define winbind_on() \ + (setenv(WINBINDD_DONT_ENV, "0", 1) == 0) + +int winbind_write_sock(void *buffer, int count, int recursing, int need_priv); +int winbind_read_sock(void *buffer, int count); +void winbind_close_sock(void); + +const char *nss_err_str(NSS_STATUS ret); diff --git a/nsswitch/winbind_krb5_locator.c b/nsswitch/winbind_krb5_locator.c new file mode 100644 index 0000000000..b9e35bdec5 --- /dev/null +++ b/nsswitch/winbind_krb5_locator.c @@ -0,0 +1,411 @@ +/* + Unix SMB/CIFS implementation. + kerberos locator plugin + Copyright (C) Guenther Deschner 2007-2008 + + 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 3 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, see . +*/ + +#include "nsswitch/winbind_client.h" +#include "libwbclient/wbclient.h" + +#ifndef DEBUG_KRB5 +#undef DEBUG_KRB5 +#endif + +#if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H) + +#include + +#ifndef KRB5_PLUGIN_NO_HANDLE +#define KRB5_PLUGIN_NO_HANDLE KRB5_KDC_UNREACH /* Heimdal */ +#endif + +static const char *get_service_from_locate_service_type(enum locate_service_type svc) +{ + switch (svc) { + case locate_service_kdc: + case locate_service_master_kdc: + return "88"; + case locate_service_kadmin: + case locate_service_krb524: + /* not supported */ + return NULL; + case locate_service_kpasswd: + return "464"; + default: + break; + } + return NULL; + +} + +#ifdef DEBUG_KRB5 +static const char *locate_service_type_name(enum locate_service_type svc) +{ + switch (svc) { + case locate_service_kdc: + return "locate_service_kdc"; + case locate_service_master_kdc: + return "locate_service_master_kdc"; + case locate_service_kadmin: + return "locate_service_kadmin"; + case locate_service_krb524: + return "locate_service_krb524"; + case locate_service_kpasswd: + return "locate_service_kpasswd"; + default: + break; + } + return NULL; +} + +static const char *socktype_name(int socktype) +{ + switch (socktype) { + case SOCK_STREAM: + return "SOCK_STREAM"; + case SOCK_DGRAM: + return "SOCK_DGRAM"; + default: + break; + } + return "unknown"; +} + +static const char *family_name(int family) +{ + switch (family) { + case AF_UNSPEC: + return "AF_UNSPEC"; + case AF_INET: + return "AF_INET"; +#if defined(HAVE_IPV6) + case AF_INET6: + return "AF_INET6"; +#endif + default: + break; + } + return "unknown"; +} +#endif + +/** + * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones + * + * @param svc + * @param realm string + * @param socktype integer + * @param family integer + * + * @return integer. + */ + +static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc, + const char *realm, + int socktype, + int family) +{ + if (!realm || strlen(realm) == 0) { + return EINVAL; + } + + switch (svc) { + case locate_service_kdc: + case locate_service_master_kdc: + case locate_service_kpasswd: + break; + case locate_service_kadmin: + case locate_service_krb524: + return KRB5_PLUGIN_NO_HANDLE; + default: + return EINVAL; + } + + switch (family) { + case AF_UNSPEC: + case AF_INET: + break; +#if defined(HAVE_IPV6) + case AF_INET6: + break; +#endif + default: + return EINVAL; + } + + switch (socktype) { + case SOCK_STREAM: + case SOCK_DGRAM: + case 0: /* Heimdal uses that */ + break; + default: + return EINVAL; + } + + return 0; +} + +/** + * Try to get addrinfo for a given host and call the krb5 callback + * + * @param name string + * @param service string + * @param in struct addrinfo hint + * @param cbfunc krb5 callback function + * @param cbdata void pointer cbdata + * + * @return krb5_error_code. + */ + +static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name, + const char *service, + struct addrinfo *in, + int (*cbfunc)(void *, int, struct sockaddr *), + void *cbdata) +{ + struct addrinfo *out = NULL; + int ret; + int count = 3; + + while (count) { + + ret = getaddrinfo(name, service, in, &out); + if (ret == 0) { + break; + } + + if (ret == EAI_AGAIN) { + count--; + continue; + } + +#ifdef DEBUG_KRB5 + fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " + "getaddrinfo failed: %s (%d)\n", + (unsigned int)getpid(), gai_strerror(ret), ret); +#endif + + return KRB5_PLUGIN_NO_HANDLE; + } + + ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr); +#ifdef DEBUG_KRB5 + if (ret) { + fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " + "failed to call callback: %s (%d)\n", + (unsigned int)getpid(), error_message(ret), ret); + } +#endif + + freeaddrinfo(out); + return ret; +} + +/** + * PUBLIC INTERFACE: locate init + * + * @param context krb5_context + * @param privata_data pointer to private data pointer + * + * @return krb5_error_code. + */ + +static krb5_error_code smb_krb5_locator_init(krb5_context context, + void **private_data) +{ + return 0; +} + +/** + * PUBLIC INTERFACE: close locate + * + * @param private_data pointer to private data + * + * @return void. + */ + +static void smb_krb5_locator_close(void *private_data) +{ + return; +} + + +static bool ask_winbind(const char *realm, char **dcname) +{ + wbcErr wbc_status; + const char *dc = NULL; + struct wbcDomainControllerInfoEx *dc_info = NULL; + uint32_t flags; + + flags = WBC_LOOKUP_DC_KDC_REQUIRED | + WBC_LOOKUP_DC_IS_DNS_NAME | + WBC_LOOKUP_DC_RETURN_DNS_NAME | + WBC_LOOKUP_DC_IP_REQUIRED; + + wbc_status = wbcLookupDomainControllerEx(realm, NULL, NULL, flags, &dc_info); + + if (!WBC_ERROR_IS_OK(wbc_status)) { +#ifdef DEBUG_KRB5 + fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: failed with: %s\n", + (unsigned int)getpid(), wbcErrorString(wbc_status)); +#endif + return false; + } + + if (dc_info->dc_address) { + dc = dc_info->dc_address; + if (dc[0] == '\\') dc++; + if (dc[0] == '\\') dc++; + } + + if (!dc && dc_info->dc_unc) { + dc = dc_info->dc_unc; + if (dc[0] == '\\') dc++; + if (dc[0] == '\\') dc++; + } + + if (!dc) { + wbcFreeMemory(dc_info); + return false; + } + + *dcname = strdup(dc); + if (!*dcname) { + wbcFreeMemory(dc_info); + return false; + } + + wbcFreeMemory(dc_info); + return true; +} + +/** + * PUBLIC INTERFACE: locate lookup + * + * @param private_data pointer to private data + * @param svc enum locate_service_type. + * @param realm string + * @param socktype integer + * @param family integer + * @param cbfunc callback function to send back entries + * @param cbdata void pointer to cbdata + * + * @return krb5_error_code. + */ + +static krb5_error_code smb_krb5_locator_lookup(void *private_data, + enum locate_service_type svc, + const char *realm, + int socktype, + int family, + int (*cbfunc)(void *, int, struct sockaddr *), + void *cbdata) +{ + krb5_error_code ret; + struct addrinfo aihints; + char *kdc_name = NULL; + const char *service = get_service_from_locate_service_type(svc); + + ZERO_STRUCT(aihints); + +#ifdef DEBUG_KRB5 + fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: called for '%s' " + "svc: '%s' (%d) " + "socktype: '%s' (%d), family: '%s' (%d)\n", + (unsigned int)getpid(), realm, + locate_service_type_name(svc), svc, + socktype_name(socktype), socktype, + family_name(family), family); +#endif + ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, + family); + if (ret) { +#ifdef DEBUG_KRB5 + fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " + "returning ret: %s (%d)\n", + (unsigned int)getpid(), error_message(ret), ret); +#endif + return ret; + } + + if (!winbind_env_set()) { + if (!ask_winbind(realm, &kdc_name)) { +#ifdef DEBUG_KRB5 + fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " + "failed to query winbindd\n", + (unsigned int)getpid()); +#endif + goto failed; + } + } else { + const char *env = NULL; + char *var = NULL; + if (asprintf(&var, "%s_%s", + WINBINDD_LOCATOR_KDC_ADDRESS, realm) == -1) { + goto failed; + } + env = getenv(var); + if (!env) { +#ifdef DEBUG_KRB5 + fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " + "failed to get kdc from env %s\n", + (unsigned int)getpid(), var); +#endif + free(var); + goto failed; + } + free(var); + + kdc_name = strdup(env); + if (!kdc_name) { + goto failed; + } + } +#ifdef DEBUG_KRB5 + fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " + "got '%s' for '%s' from winbindd\n", (unsigned int)getpid(), + kdc_name, realm); +#endif + + aihints.ai_family = family; + aihints.ai_socktype = socktype; + + ret = smb_krb5_locator_call_cbfunc(kdc_name, + service, + &aihints, + cbfunc, cbdata); + SAFE_FREE(kdc_name); + + return ret; + + failed: + return KRB5_PLUGIN_NO_HANDLE; +} + +#ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H +#define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */ +#else +#define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */ +#endif + +const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = { + 0, /* version */ + smb_krb5_locator_init, + smb_krb5_locator_close, + smb_krb5_locator_lookup, +}; + +#endif diff --git a/nsswitch/winbind_nss.h b/nsswitch/winbind_nss.h new file mode 100644 index 0000000000..05e07ad5d3 --- /dev/null +++ b/nsswitch/winbind_nss.h @@ -0,0 +1,76 @@ +/* + Unix SMB/CIFS implementation. + + A common place to work out how to define NSS_STATUS on various + platforms. + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _NSSWITCH_NSS_H +#define _NSSWITCH_NSS_H + +#ifdef HAVE_NSS_COMMON_H + +/* + * Sun Solaris + */ + +#include "nsswitch/winbind_nss_solaris.h" + +#elif HAVE_NSS_H + +/* + * Linux (glibc) + */ + +#include "nsswitch/winbind_nss_linux.h" + +#elif HAVE_NS_API_H + +/* + * SGI IRIX + */ + +#include "nsswitch/winbind_nss_irix.h" + +#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) + +/* HP-UX 11 */ + +#include "nsswitch/winbind_nss_hpux.h" + +#elif defined(__NetBSD__) && defined(HAVE_GETPWENT_R) + +/* + * NetBSD 3 and newer + */ + +#include "nsswitch/winbind_nss_netbsd.h" + +#else /* Nothing's defined. Neither gnu nor netbsd nor sun nor hp */ + +typedef enum +{ + NSS_STATUS_SUCCESS=0, + NSS_STATUS_NOTFOUND=1, + NSS_STATUS_UNAVAIL=2, + NSS_STATUS_TRYAGAIN=3 +} NSS_STATUS; + +#endif + +#endif /* _NSSWITCH_NSS_H */ diff --git a/nsswitch/winbind_nss_aix.c b/nsswitch/winbind_nss_aix.c new file mode 100644 index 0000000000..17578cf350 --- /dev/null +++ b/nsswitch/winbind_nss_aix.c @@ -0,0 +1,1076 @@ +/* + Unix SMB/CIFS implementation. + + AIX loadable authentication module, providing identification and + authentication routines against Samba winbind/Windows NT Domain + + Copyright (C) Tim Potter 2003 + Copyright (C) Steve Roylance 2003 + Copyright (C) Andrew Tridgell 2003-2004 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +/* + + To install this module copy nsswitch/WINBIND to /usr/lib/security and add + "WINBIND" in /usr/lib/security/methods.cfg and /etc/security/user + + Note that this module also provides authentication and password + changing routines, so you do not need to install the winbind PAM + module. + + see + http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm + for some information in the interface that this module implements + + Many thanks to Julianne Haugh for explaining some of the finer + details of this interface. + + To debug this module use uess_test.c (which you can get from tridge) + or set "options=debug" in /usr/lib/security/methods.cfg + +*/ + +#include "winbind_client.h" +#include + +/* enable this to log which entry points have not been + completed yet */ +#define LOG_UNIMPLEMENTED_CALLS 0 + + +#define WB_AIX_ENCODED '_' + +static int debug_enabled; + + +static void logit(const char *format, ...) +{ + va_list ap; + FILE *f; + if (!debug_enabled) { + return; + } + f = fopen("/tmp/WINBIND_DEBUG.log", "a"); + if (!f) return; + va_start(ap, format); + vfprintf(f, format, ap); + va_end(ap); + fclose(f); +} + + +#define HANDLE_ERRORS(ret) do { \ + if ((ret) == NSS_STATUS_NOTFOUND) { \ + errno = ENOENT; \ + return NULL; \ + } else if ((ret) != NSS_STATUS_SUCCESS) { \ + errno = EIO; \ + return NULL; \ + } \ +} while (0) + +#define STRCPY_RET(dest, src) \ +do { \ + if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \ + strcpy(dest, src); \ +} while (0) + +#define STRCPY_RETNULL(dest, src) \ +do { \ + if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \ + strcpy(dest, src); \ +} while (0) + + +/* free a passwd structure */ +static void free_pwd(struct passwd *pwd) +{ + free(pwd->pw_name); + free(pwd->pw_passwd); + free(pwd->pw_gecos); + free(pwd->pw_dir); + free(pwd->pw_shell); + free(pwd); +} + +/* free a group structure */ +static void free_grp(struct group *grp) +{ + int i; + + free(grp->gr_name); + free(grp->gr_passwd); + + if (!grp->gr_mem) { + free(grp); + return; + } + + for (i=0; grp->gr_mem[i]; i++) { + free(grp->gr_mem[i]); + } + + free(grp->gr_mem); + free(grp); +} + + +/* replace commas with nulls, and null terminate */ +static void replace_commas(char *s) +{ + char *p, *p0=s; + for (p=strchr(s, ','); p; p = strchr(p+1, ',')) { + *p=0; + p0 = p+1; + } + + p0[strlen(p0)+1] = 0; +} + + +/* the decode_*() routines are used to cope with the fact that AIX 5.2 + and below cannot handle user or group names longer than 8 + characters in some interfaces. We use the normalize method to + provide a mapping to a username that fits, by using the form '_UID' + or '_GID'. + + this only works if you can guarantee that the WB_AIX_ENCODED char + is not used as the first char of any other username +*/ +static unsigned decode_id(const char *name) +{ + unsigned id; + sscanf(name+1, "%u", &id); + return id; +} + +static struct passwd *wb_aix_getpwuid(uid_t uid); + +static char *decode_user(const char *name) +{ + struct passwd *pwd; + unsigned id; + char *ret; + + sscanf(name+1, "%u", &id); + pwd = wb_aix_getpwuid(id); + if (!pwd) { + return NULL; + } + ret = strdup(pwd->pw_name); + + free_pwd(pwd); + + logit("decoded '%s' -> '%s'\n", name, ret); + + return ret; +} + + +/* + fill a struct passwd from a winbindd_pw struct, allocating as a single block +*/ +static struct passwd *fill_pwent(struct winbindd_pw *pw) +{ + struct passwd *result; + + result = calloc(1, sizeof(struct passwd)); + if (!result) { + errno = ENOMEM; + return NULL; + } + + result->pw_uid = pw->pw_uid; + result->pw_gid = pw->pw_gid; + result->pw_name = strdup(pw->pw_name); + result->pw_passwd = strdup(pw->pw_passwd); + result->pw_gecos = strdup(pw->pw_gecos); + result->pw_dir = strdup(pw->pw_dir); + result->pw_shell = strdup(pw->pw_shell); + + return result; +} + + +/* + fill a struct group from a winbindd_pw struct, allocating as a single block +*/ +static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem) +{ + int i; + struct group *result; + char *p, *name; + + result = calloc(1, sizeof(struct group)); + if (!result) { + errno = ENOMEM; + return NULL; + } + + result->gr_gid = gr->gr_gid; + + result->gr_name = strdup(gr->gr_name); + result->gr_passwd = strdup(gr->gr_passwd); + + /* Group membership */ + if ((gr->num_gr_mem < 0) || !gr_mem) { + gr->num_gr_mem = 0; + } + + if (gr->num_gr_mem == 0) { + /* Group is empty */ + return result; + } + + result->gr_mem = (char **)malloc(sizeof(char *) * (gr->num_gr_mem+1)); + if (!result->gr_mem) { + errno = ENOMEM; + return NULL; + } + + /* Start looking at extra data */ + i=0; + for (name = strtok_r(gr_mem, ",", &p); + name; + name = strtok_r(NULL, ",", &p)) { + if (i == gr->num_gr_mem) { + break; + } + result->gr_mem[i] = strdup(name); + i++; + } + + /* Terminate list */ + result->gr_mem[i] = NULL; + + return result; +} + + + +/* take a group id and return a filled struct group */ +static struct group *wb_aix_getgrgid(gid_t gid) +{ + struct winbindd_response response; + struct winbindd_request request; + struct group *grp; + NSS_STATUS ret; + + logit("getgrgid %d\n", gid); + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.gid = gid; + + ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response); + + logit("getgrgid ret=%d\n", ret); + + HANDLE_ERRORS(ret); + + grp = fill_grent(&response.data.gr, response.extra_data.data); + + winbindd_free_response(&response); + + return grp; +} + +/* take a group name and return a filled struct group */ +static struct group *wb_aix_getgrnam(const char *name) +{ + struct winbindd_response response; + struct winbindd_request request; + NSS_STATUS ret; + struct group *grp; + + if (*name == WB_AIX_ENCODED) { + return wb_aix_getgrgid(decode_id(name)); + } + + logit("getgrnam '%s'\n", name); + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + STRCPY_RETNULL(request.data.groupname, name); + + ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); + + HANDLE_ERRORS(ret); + + grp = fill_grent(&response.data.gr, response.extra_data.data); + + winbindd_free_response(&response); + + return grp; +} + + +/* this call doesn't have to fill in the gr_mem, but we do anyway + for simplicity */ +static struct group *wb_aix_getgracct(void *id, int type) +{ + if (type == 1) { + return wb_aix_getgrnam((char *)id); + } + if (type == 0) { + return wb_aix_getgrgid(*(int *)id); + } + errno = EINVAL; + return NULL; +} + + +/* take a username and return a string containing a comma-separated + list of group id numbers to which the user belongs */ +static char *wb_aix_getgrset(char *user) +{ + struct winbindd_response response; + struct winbindd_request request; + NSS_STATUS ret; + int i, idx; + char *tmpbuf; + int num_gids; + gid_t *gid_list; + char *r_user = user; + + if (*user == WB_AIX_ENCODED) { + r_user = decode_user(r_user); + if (!r_user) { + errno = ENOENT; + return NULL; + } + } + + logit("getgrset '%s'\n", r_user); + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + STRCPY_RETNULL(request.data.username, r_user); + + if (*user == WB_AIX_ENCODED) { + free(r_user); + } + + ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); + + HANDLE_ERRORS(ret); + + num_gids = response.data.num_entries; + gid_list = (gid_t *)response.extra_data.data; + + /* allocate a space large enough to contruct the string */ + tmpbuf = malloc(num_gids*12); + if (!tmpbuf) { + return NULL; + } + + for (idx=i=0; i < num_gids-1; i++) { + idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]); + } + idx += sprintf(tmpbuf+idx, "%u", gid_list[i]); + + winbindd_free_response(&response); + + return tmpbuf; +} + + +/* take a uid and return a filled struct passwd */ +static struct passwd *wb_aix_getpwuid(uid_t uid) +{ + struct winbindd_response response; + struct winbindd_request request; + NSS_STATUS ret; + struct passwd *pwd; + + logit("getpwuid '%d'\n", uid); + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.uid = uid; + + ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); + + HANDLE_ERRORS(ret); + + pwd = fill_pwent(&response.data.pw); + + winbindd_free_response(&response); + + logit("getpwuid gave ptr %p\n", pwd); + + return pwd; +} + + +/* take a username and return a filled struct passwd */ +static struct passwd *wb_aix_getpwnam(const char *name) +{ + struct winbindd_response response; + struct winbindd_request request; + NSS_STATUS ret; + struct passwd *pwd; + + if (*name == WB_AIX_ENCODED) { + return wb_aix_getpwuid(decode_id(name)); + } + + logit("getpwnam '%s'\n", name); + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + STRCPY_RETNULL(request.data.username, name); + + ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); + + HANDLE_ERRORS(ret); + + pwd = fill_pwent(&response.data.pw); + + winbindd_free_response(&response); + + logit("getpwnam gave ptr %p\n", pwd); + + return pwd; +} + +/* + list users +*/ +static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + int len; + char *s; + + if (size != 1 || strcmp(attributes[0], S_USERS) != 0) { + logit("invalid lsuser op\n"); + errno = EINVAL; + return -1; + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response); + if (ret != 0) { + errno = EINVAL; + return -1; + } + + len = strlen(response.extra_data.data); + + s = malloc(len+2); + if (!s) { + winbindd_free_response(&response); + errno = ENOMEM; + return -1; + } + + memcpy(s, response.extra_data.data, len+1); + + replace_commas(s); + + results[0].attr_un.au_char = s; + results[0].attr_flag = 0; + + winbindd_free_response(&response); + + return 0; +} + + +/* + list groups +*/ +static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + int len; + char *s; + + if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) { + logit("invalid lsgroup op\n"); + errno = EINVAL; + return -1; + } + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response); + if (ret != 0) { + errno = EINVAL; + return -1; + } + + len = strlen(response.extra_data.data); + + s = malloc(len+2); + if (!s) { + winbindd_free_response(&response); + errno = ENOMEM; + return -1; + } + + memcpy(s, response.extra_data.data, len+1); + + replace_commas(s); + + results[0].attr_un.au_char = s; + results[0].attr_flag = 0; + + winbindd_free_response(&response); + + return 0; +} + + +static attrval_t pwd_to_group(struct passwd *pwd) +{ + attrval_t r; + struct group *grp = wb_aix_getgrgid(pwd->pw_gid); + + if (!grp) { + r.attr_flag = EINVAL; + } else { + r.attr_flag = 0; + r.attr_un.au_char = strdup(grp->gr_name); + free_grp(grp); + } + + return r; +} + +static attrval_t pwd_to_groupsids(struct passwd *pwd) +{ + attrval_t r; + char *s, *p; + + if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) { + r.attr_flag = EINVAL; + return r; + } + + if ( (p = malloc(strlen(s)+2)) == NULL ) { + r.attr_flag = ENOMEM; + return r; + } + + strcpy(p, s); + replace_commas(p); + free(s); + + r.attr_un.au_char = p; + + return r; +} + +static attrval_t pwd_to_sid(struct passwd *pwd) +{ + struct winbindd_request request; + struct winbindd_response response; + attrval_t r; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.uid = pwd->pw_uid; + + if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) != + NSS_STATUS_SUCCESS) { + r.attr_flag = ENOENT; + } else { + r.attr_flag = 0; + r.attr_un.au_char = strdup(response.data.sid.sid); + } + + return r; +} + +static int wb_aix_user_attrib(const char *key, char *attributes[], + attrval_t results[], int size) +{ + struct passwd *pwd; + int i; + + pwd = wb_aix_getpwnam(key); + if (!pwd) { + errno = ENOENT; + return -1; + } + + for (i=0;ipw_uid; +#ifdef _AIXVERSION_530 + } else if (strcmp(attributes[i], S_PGID) == 0) { + results[i].attr_un.au_int = pwd->pw_gid; +#endif + } else if (strcmp(attributes[i], S_PWD) == 0) { + results[i].attr_un.au_char = strdup(pwd->pw_passwd); + } else if (strcmp(attributes[i], S_HOME) == 0) { + results[i].attr_un.au_char = strdup(pwd->pw_dir); + } else if (strcmp(attributes[i], S_SHELL) == 0) { + results[i].attr_un.au_char = strdup(pwd->pw_shell); + } else if (strcmp(attributes[i], S_REGISTRY) == 0) { + results[i].attr_un.au_char = strdup("WINBIND"); + } else if (strcmp(attributes[i], S_GECOS) == 0) { + results[i].attr_un.au_char = strdup(pwd->pw_gecos); + } else if (strcmp(attributes[i], S_PGRP) == 0) { + results[i] = pwd_to_group(pwd); + } else if (strcmp(attributes[i], S_GROUPS) == 0) { + results[i] = pwd_to_groupsids(pwd); + } else if (strcmp(attributes[i], "SID") == 0) { + results[i] = pwd_to_sid(pwd); + } else { + logit("Unknown user attribute '%s'\n", attributes[i]); + results[i].attr_flag = EINVAL; + } + } + + free_pwd(pwd); + + return 0; +} + +static int wb_aix_group_attrib(const char *key, char *attributes[], + attrval_t results[], int size) +{ + struct group *grp; + int i; + + grp = wb_aix_getgrnam(key); + if (!grp) { + errno = ENOENT; + return -1; + } + + for (i=0;igr_passwd); + } else if (strcmp(attributes[i], S_ID) == 0) { + results[i].attr_un.au_int = grp->gr_gid; + } else { + logit("Unknown group attribute '%s'\n", attributes[i]); + results[i].attr_flag = EINVAL; + } + } + + free_grp(grp); + + return 0; +} + + +/* + called for user/group enumerations +*/ +static int wb_aix_getentry(char *key, char *table, char *attributes[], + attrval_t results[], int size) +{ + logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n", + key, table, size, attributes[0]); + + if (strcmp(key, "ALL") == 0 && + strcmp(table, "user") == 0) { + return wb_aix_lsuser(attributes, results, size); + } + + if (strcmp(key, "ALL") == 0 && + strcmp(table, "group") == 0) { + return wb_aix_lsgroup(attributes, results, size); + } + + if (strcmp(table, "user") == 0) { + return wb_aix_user_attrib(key, attributes, results, size); + } + + if (strcmp(table, "group") == 0) { + return wb_aix_group_attrib(key, attributes, results, size); + } + + logit("Unknown getentry operation key='%s' table='%s'\n", key, table); + + errno = ENOSYS; + return -1; +} + + + +/* + called to start the backend +*/ +static void *wb_aix_open(const char *name, const char *domain, int mode, char *options) +{ + if (strstr(options, "debug")) { + debug_enabled = 1; + } + logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain, + mode, options); + return NULL; +} + +static void wb_aix_close(void *token) +{ + logit("close\n"); + return; +} + +#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST +/* + return a list of additional attributes supported by the backend +*/ +static attrlist_t **wb_aix_attrlist(void) +{ + /* pretty confusing but we are allocating the array of pointers + and the structures we'll be pointing to all at once. So + you need N+1 pointers and N structures. */ + + attrlist_t **ret = NULL; + attrlist_t *offset = NULL; + int i; + int n; + size_t size; + + struct attr_types { + const char *name; + int flags; + int type; + } attr_list[] = { + /* user attributes */ + {S_ID, AL_USERATTR, SEC_INT}, + {S_PGRP, AL_USERATTR, SEC_CHAR}, + {S_HOME, AL_USERATTR, SEC_CHAR}, + {S_SHELL, AL_USERATTR, SEC_CHAR}, +#ifdef _AIXVERSION_530 + {S_PGID, AL_USERATTR, SEC_INT}, +#endif + {S_GECOS, AL_USERATTR, SEC_CHAR}, + {S_SHELL, AL_USERATTR, SEC_CHAR}, + {S_PGRP, AL_USERATTR, SEC_CHAR}, + {S_GROUPS, AL_USERATTR, SEC_LIST}, + {"SID", AL_USERATTR, SEC_CHAR}, + + /* group attributes */ + {S_ID, AL_GROUPATTR, SEC_INT} + }; + + logit("method attrlist called\n"); + + n = sizeof(attr_list) / sizeof(struct attr_types); + size = (n*sizeof(attrlist_t *)); + + if ( (ret = malloc( size )) == NULL ) { + errno = ENOMEM; + return NULL; + } + + /* offset to where the structures start in the buffer */ + + offset = (attrlist_t *)(ret + n); + + /* now loop over the user_attr_list[] array and add + all the members */ + + for ( i=0; ial_name = strdup(attr_list[i].name); + a->al_flags = attr_list[i].flags; + a->al_type = attr_list[i].type; + + ret[i] = a; + } + ret[n] = NULL; + + return ret; +} +#endif + + +/* + turn a long username into a short one. Needed to cope with the 8 char + username limit in AIX 5.2 and below +*/ +static int wb_aix_normalize(char *longname, char *shortname) +{ + struct passwd *pwd; + + logit("normalize '%s'\n", longname); + + /* automatically cope with AIX 5.3 with longer usernames + when it comes out */ + if (S_NAMELEN > strlen(longname)) { + strcpy(shortname, longname); + return 1; + } + + pwd = wb_aix_getpwnam(longname); + if (!pwd) { + errno = ENOENT; + return 0; + } + + sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid); + + free_pwd(pwd); + + return 1; +} + + +/* + authenticate a user + */ +static int wb_aix_authenticate(char *user, char *pass, + int *reenter, char **message) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + char *r_user = user; + + logit("authenticate '%s' response='%s'\n", user, pass); + + *reenter = 0; + *message = NULL; + + /* Send off request */ + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (*user == WB_AIX_ENCODED) { + r_user = decode_user(r_user); + if (!r_user) { + return AUTH_NOTFOUND; + } + } + + STRCPY_RET(request.data.auth.user, r_user); + STRCPY_RET(request.data.auth.pass, pass); + + if (*user == WB_AIX_ENCODED) { + free(r_user); + } + + result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); + + winbindd_free_response(&response); + + logit("auth result %d for '%s'\n", result, user); + + if (result == NSS_STATUS_SUCCESS) { + errno = 0; + return AUTH_SUCCESS; + } + + return AUTH_FAILURE; +} + + +/* + change a user password +*/ +static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + char *r_user = user; + + if (*user == WB_AIX_ENCODED) { + r_user = decode_user(r_user); + if (!r_user) { + errno = ENOENT; + return -1; + } + } + + logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass); + + *message = NULL; + + /* Send off request */ + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + STRCPY_RET(request.data.chauthtok.user, r_user); + STRCPY_RET(request.data.chauthtok.oldpass, oldpass); + STRCPY_RET(request.data.chauthtok.newpass, newpass); + + if (*user == WB_AIX_ENCODED) { + free(r_user); + } + + result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response); + + winbindd_free_response(&response); + + if (result == NSS_STATUS_SUCCESS) { + errno = 0; + return 0; + } + + errno = EINVAL; + return -1; +} + +/* + don't do any password strength testing for now +*/ +static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass, + char **message) +{ + logit("passwdresrictions called for '%s'\n", user); + return 0; +} + + +static int wb_aix_passwdexpired(char *user, char **message) +{ + logit("passwdexpired '%s'\n", user); + /* we should check the account bits here */ + return 0; +} + + +/* + we can't return a crypt() password +*/ +static char *wb_aix_getpasswd(char *user) +{ + logit("getpasswd '%s'\n", user); + errno = ENOSYS; + return NULL; +} + +/* + this is called to update things like the last login time. We don't + currently pass this onto the DC +*/ +static int wb_aix_putentry(char *key, char *table, char *attributes[], + attrval_t values[], int size) +{ + logit("putentry key='%s' table='%s' attrib='%s'\n", + key, table, size>=1?attributes[0]:""); + errno = ENOSYS; + return -1; +} + +static int wb_aix_commit(char *key, char *table) +{ + logit("commit key='%s' table='%s'\n"); + errno = ENOSYS; + return -1; +} + +static int wb_aix_getgrusers(char *group, void *result, int type, int *size) +{ + logit("getgrusers group='%s'\n", group); + errno = ENOSYS; + return -1; +} + + +#define DECL_METHOD(x) \ +int method_ ## x(void) \ +{ \ + logit("UNIMPLEMENTED METHOD '%s'\n", #x); \ + errno = EINVAL; \ + return -1; \ +} + +#if LOG_UNIMPLEMENTED_CALLS +DECL_METHOD(delgroup); +DECL_METHOD(deluser); +DECL_METHOD(newgroup); +DECL_METHOD(newuser); +DECL_METHOD(putgrent); +DECL_METHOD(putgrusers); +DECL_METHOD(putpwent); +DECL_METHOD(lock); +DECL_METHOD(unlock); +DECL_METHOD(getcred); +DECL_METHOD(setcred); +DECL_METHOD(deletecred); +#endif + +int wb_aix_init(struct secmethod_table *methods) +{ + ZERO_STRUCTP(methods); + +#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION + methods->method_version = SECMETHOD_VERSION_520; +#endif + + methods->method_getgrgid = wb_aix_getgrgid; + methods->method_getgrnam = wb_aix_getgrnam; + methods->method_getgrset = wb_aix_getgrset; + methods->method_getpwnam = wb_aix_getpwnam; + methods->method_getpwuid = wb_aix_getpwuid; + methods->method_getentry = wb_aix_getentry; + methods->method_open = wb_aix_open; + methods->method_close = wb_aix_close; + methods->method_normalize = wb_aix_normalize; + methods->method_passwdexpired = wb_aix_passwdexpired; + methods->method_putentry = wb_aix_putentry; + methods->method_getpasswd = wb_aix_getpasswd; + methods->method_authenticate = wb_aix_authenticate; + methods->method_commit = wb_aix_commit; + methods->method_chpass = wb_aix_chpass; + methods->method_passwdrestrictions = wb_aix_passwdrestrictions; + methods->method_getgracct = wb_aix_getgracct; + methods->method_getgrusers = wb_aix_getgrusers; +#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST + methods->method_attrlist = wb_aix_attrlist; +#endif + +#if LOG_UNIMPLEMENTED_CALLS + methods->method_delgroup = method_delgroup; + methods->method_deluser = method_deluser; + methods->method_newgroup = method_newgroup; + methods->method_newuser = method_newuser; + methods->method_putgrent = method_putgrent; + methods->method_putgrusers = method_putgrusers; + methods->method_putpwent = method_putpwent; + methods->method_lock = method_lock; + methods->method_unlock = method_unlock; + methods->method_getcred = method_getcred; + methods->method_setcred = method_setcred; + methods->method_deletecred = method_deletecred; +#endif + + return AUTH_SUCCESS; +} diff --git a/nsswitch/winbind_nss_config.h b/nsswitch/winbind_nss_config.h new file mode 100644 index 0000000000..3e2ce68252 --- /dev/null +++ b/nsswitch/winbind_nss_config.h @@ -0,0 +1,70 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WINBIND_NSS_CONFIG_H +#define _WINBIND_NSS_CONFIG_H + +/* shutup the compiler warnings due to krb5.h on 64-bit sles9 */ +#ifdef SIZEOF_LONG +#undef SIZEOF_LONG +#endif + +/* + * we don't need socket wrapper + * nor nss wrapper here and we don't + * want to depend on swrap_close() + * so we better disable both + */ +#define SOCKET_WRAPPER_NOT_REPLACE +#define NSS_WRAPPER_NOT_REPLACE + +/* Include header files from data in config.h file */ + +#ifndef NO_CONFIG_H +#include "../replace/replace.h" +#endif + +#include "system/filesys.h" +#include "system/network.h" +#include "system/passwd.h" + +#include "nsswitch/winbind_nss.h" + +/* I'm trying really hard not to include anything from smb.h with the + result of some silly looking redeclaration of structures. */ + +#ifndef FSTRING_LEN +#define FSTRING_LEN 256 +typedef char fstring[FSTRING_LEN]; +#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1) +#endif + +/* Some systems (SCO) treat UNIX domain sockets as FIFOs */ + +#ifndef S_IFSOCK +#define S_IFSOCK S_IFIFO +#endif + +#ifndef S_ISSOCK +#define S_ISSOCK(mode) ((mode & S_IFSOCK) == S_IFSOCK) +#endif + +#endif diff --git a/nsswitch/winbind_nss_freebsd.c b/nsswitch/winbind_nss_freebsd.c new file mode 100644 index 0000000000..ac230c8a9a --- /dev/null +++ b/nsswitch/winbind_nss_freebsd.c @@ -0,0 +1,79 @@ +/* + Unix SMB/CIFS implementation. + + AIX loadable authentication module, providing identification + routines against Samba winbind/Windows NT Domain + + Copyright (C) Aaron Collins 2003 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "winbind_client.h" + +/* Make sure that the module gets registered needed by freebsd 5.1 */ + +extern enum nss_status _nss_winbind_getgrent_r(struct group *, char *, size_t, + int *); +extern enum nss_status _nss_winbind_getgrnam_r(const char *, struct group *, + char *, size_t, int *); +extern enum nss_status _nss_winbind_getgrgid_r(gid_t gid, struct group *, char *, + size_t, int *); +extern enum nss_status _nss_winbind_setgrent(void); +extern enum nss_status _nss_winbind_endgrent(void); + +extern enum nss_status _nss_winbind_getpwent_r(struct passwd *, char *, size_t, + int *); +extern enum nss_status _nss_winbind_getpwnam_r(const char *, struct passwd *, + char *, size_t, int *); +extern enum nss_status _nss_winbind_getpwuid_r(gid_t gid, struct passwd *, char *, + size_t, int *); +extern enum nss_status _nss_winbind_setpwent(void); +extern enum nss_status _nss_winbind_endpwent(void); + +NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r); +NSS_METHOD_PROTOTYPE(__nss_compat_setgrent); +NSS_METHOD_PROTOTYPE(__nss_compat_endgrent); + +NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r); +NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r); +NSS_METHOD_PROTOTYPE(__nss_compat_setpwent); +NSS_METHOD_PROTOTYPE(__nss_compat_endpwent); + +static ns_mtab methods[] = { +{ NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_winbind_getgrnam_r }, +{ NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_winbind_getgrgid_r }, +{ NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_winbind_getgrent_r }, +{ NSDB_GROUP, "endgrent", __nss_compat_setgrent, _nss_winbind_setgrent }, +{ NSDB_GROUP, "setgrent", __nss_compat_endgrent, _nss_winbind_endgrent }, + +{ NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_winbind_getpwnam_r }, +{ NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_winbind_getpwuid_r }, +{ NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_winbind_getpwent_r }, +{ NSDB_PASSWD, "endpwent", __nss_compat_setpwent, _nss_winbind_setpwent }, +{ NSDB_PASSWD, "setpwent", __nss_compat_endpwent, _nss_winbind_endpwent }, + +}; + +ns_mtab * +nss_module_register(const char *source, unsigned int *mtabsize, + nss_module_unregister_fn *unreg) +{ + *mtabsize = sizeof(methods)/sizeof(methods[0]); + *unreg = NULL; + return (methods); +} diff --git a/nsswitch/winbind_nss_hpux.h b/nsswitch/winbind_nss_hpux.h new file mode 100644 index 0000000000..40a352d4d3 --- /dev/null +++ b/nsswitch/winbind_nss_hpux.h @@ -0,0 +1,137 @@ +/* + Unix SMB/CIFS implementation. + + Donated by HP to enable Winbindd to build on HPUX 11.x. + Copyright (C) Jeremy Allison 2002. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#ifndef _WINBIND_NSS_HPUX_H +#define _WINBIND_NSS_HPUX_H + +#include + +#define NSS_STATUS_SUCCESS NSS_SUCCESS +#define NSS_STATUS_NOTFOUND NSS_NOTFOUND +#define NSS_STATUS_UNAVAIL NSS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN + +#ifdef HAVE_SYNCH_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif + +typedef enum { + NSS_SUCCESS, + NSS_NOTFOUND, + NSS_UNAVAIL, + NSS_TRYAGAIN +} nss_status_t; + +typedef nss_status_t NSS_STATUS; + +struct nss_backend; + +typedef nss_status_t (*nss_backend_op_t)(struct nss_backend *, void *args); + +struct nss_backend { + nss_backend_op_t *ops; + int n_ops; +}; +typedef struct nss_backend nss_backend_t; +typedef int nss_dbop_t; + +#include +#include +#include + +#ifndef NSS_INCLUDE_UNSAFE +#define NSS_INCLUDE_UNSAFE 1 /* Build old, MT-unsafe interfaces, */ +#endif /* NSS_INCLUDE_UNSAFE */ + +enum nss_netgr_argn { + NSS_NETGR_MACHINE, + NSS_NETGR_USER, + NSS_NETGR_DOMAIN, + NSS_NETGR_N +}; + +enum nss_netgr_status { + NSS_NETGR_FOUND, + NSS_NETGR_NO, + NSS_NETGR_NOMEM +}; + +typedef unsigned nss_innetgr_argc; +typedef char **nss_innetgr_argv; + +struct nss_innetgr_1arg { + nss_innetgr_argc argc; + nss_innetgr_argv argv; +}; + +typedef struct { + void *result; /* "result" parameter to getXbyY_r() */ + char *buffer; /* "buffer" " " */ + int buflen; /* "buflen" " " */ +} nss_XbyY_buf_t; + +extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size); +extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *); + +union nss_XbyY_key { + uid_t uid; + gid_t gid; + const char *name; + int number; + struct { + long net; + int type; + } netaddr; + struct { + const char *addr; + int len; + int type; + } hostaddr; + struct { + union { + const char *name; + int port; + } serv; + const char *proto; + } serv; + void *ether; +}; + +typedef struct nss_XbyY_args { + nss_XbyY_buf_t buf; + int stayopen; + /* + * Support for setXXXent(stayopen) + * Used only in hosts, protocols, + * networks, rpc, and services. + */ + int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen); + union nss_XbyY_key key; + + void *returnval; + int erange; + int h_errno; + nss_status_t status; +} nss_XbyY_args_t; + +#endif /* _WINBIND_NSS_HPUX_H */ diff --git a/nsswitch/winbind_nss_irix.c b/nsswitch/winbind_nss_irix.c new file mode 100644 index 0000000000..66fa4b529d --- /dev/null +++ b/nsswitch/winbind_nss_irix.c @@ -0,0 +1,633 @@ +/* + Unix SMB/CIFS implementation. + + Windows NT Domain nsswitch module + + Copyright (C) Tim Potter 2000 + Copyright (C) James Peach 2006 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "winbind_client.h" + +#ifndef PRINTF_ATTRIBUTE +#define PRINTF_ATTRIBUTE(m, n) +#endif + +#ifndef HAVE_ASPRINTF_DECL +/*PRINTFLIKE2 */ +int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#ifdef HAVE_NS_API_H +#undef STATIC +#undef DYNAMIC +#include +#endif + +/* Maximum number of users to pass back over the unix domain socket + per call. This is not a static limit on the total number of users + or groups returned in total. */ + +#define MAX_GETPWENT_USERS 250 +#define MAX_GETGRENT_USERS 250 + +/* Prototypes from wb_common.c */ + +extern int winbindd_fd; + +#ifdef HAVE_NS_API_H + +/* IRIX version */ + +static int send_next_request(nsd_file_t *, struct winbindd_request *); +static int do_list(int state, nsd_file_t *rq); + +static nsd_file_t *current_rq = NULL; +static int current_winbind_xid = 0; +static int next_winbind_xid = 0; + +typedef struct winbind_xid { + int xid; + nsd_file_t *rq; + struct winbindd_request *request; + struct winbind_xid *next; +} winbind_xid_t; + +static winbind_xid_t *winbind_xids = (winbind_xid_t *)0; + +static int +winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request) +{ + winbind_xid_t *new; + + nsd_logprintf(NSD_LOG_LOW, + "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n", + xid, rq, request); + new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t)); + if (!new) { + nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n"); + return NSD_ERROR; + } + + new->xid = xid; + new->rq = rq; + new->request = request; + new->next = winbind_xids; + winbind_xids = new; + + return NSD_CONTINUE; +} + +/* +** This routine will look down the xid list and return the request +** associated with an xid. We remove the record if it is found. +*/ +nsd_file_t * +winbind_xid_lookup(int xid, struct winbindd_request **requestp) +{ + winbind_xid_t **last, *dx; + nsd_file_t *result=0; + + for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid); + last = &dx->next, dx = dx->next); + if (dx) { + *last = dx->next; + result = dx->rq; + *requestp = dx->request; + SAFE_FREE(dx); + } + nsd_logprintf(NSD_LOG_LOW, + "entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x\n", + xid, result, dx->request); + + return result; +} + +static int +winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to) +{ + nsd_file_t *rq; + struct winbindd_request *request; + + nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n"); + rq = to->t_file; + *rqp = rq; + nsd_timeout_remove(rq); + request = to->t_clientdata; + return(send_next_request(rq, request)); +} + +static void +dequeue_request(void) +{ + nsd_file_t *rq; + struct winbindd_request *request; + + /* + * Check for queued requests + */ + if (winbind_xids) { + nsd_logprintf(NSD_LOG_MIN, "timeout (winbind) unqueue xid %d\n", + current_winbind_xid); + rq = winbind_xid_lookup(current_winbind_xid++, &request); + /* cause a timeout on the queued request so we can send it */ + nsd_timeout_new(rq,1,winbind_startnext_timeout,request); + } +} + +static int +do_request(nsd_file_t *rq, struct winbindd_request *request) +{ + if (winbind_xids == NULL) { + /* + * No outstanding requests. + * Send off the request to winbindd + */ + nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) sending request\n"); + return(send_next_request(rq, request)); + } else { + /* + * Just queue it up for now - previous callout or timout + * will start it up + */ + nsd_logprintf(NSD_LOG_MIN, + "lookup (winbind): queue request xid = %d\n", + next_winbind_xid); + return(winbind_xid_new(next_winbind_xid++, rq, request)); + } +} + +static int +winbind_callback(nsd_file_t **rqp, int fd) +{ + struct winbindd_response response; + nsd_file_t *rq; + NSS_STATUS status; + char * result = NULL; + size_t rlen; + + dequeue_request(); + + nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n"); + + rq = current_rq; + *rqp = rq; + + nsd_timeout_remove(rq); + nsd_callback_remove(fd); + + ZERO_STRUCT(response); + status = winbindd_get_response(&response); + + if (status != NSS_STATUS_SUCCESS) { + /* free any extra data area in response structure */ + winbindd_free_response(&response); + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) returning not found, status = %d\n", + status); + + switch (status) { + case NSS_STATUS_UNAVAIL: + rq->f_status = NS_UNAVAIL; + break; + case NSS_STATUS_TRYAGAIN: + rq->f_status = NS_TRYAGAIN; + break; + case NSS_STATUS_NOTFOUND: + /* FALLTHRU */ + default: + rq->f_status = NS_NOTFOUND; + } + + return NSD_NEXT; + } + + switch ((int)rq->f_cmd_data) { + case WINBINDD_WINS_BYNAME: + case WINBINDD_WINS_BYIP: + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) WINS_BYNAME | WINS_BYIP\n"); + + rlen = asprintf(&result, "%s\n", response.data.winsresp); + if (rlen == 0 || result == NULL) { + return NSD_ERROR; + } + + winbindd_free_response(&response); + + nsd_logprintf(NSD_LOG_MIN, " %s\n", result); + nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC); + return NSD_OK; + + case WINBINDD_GETPWUID: + case WINBINDD_GETPWNAM: + { + struct winbindd_pw *pw = &response.data.pw; + + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) GETPWUID | GETPWUID\n"); + + rlen = asprintf(&result,"%s:%s:%d:%d:%s:%s:%s\n", + pw->pw_name, + pw->pw_passwd, + pw->pw_uid, + pw->pw_gid, + pw->pw_gecos, + pw->pw_dir, + pw->pw_shell); + if (rlen == 0 || result == NULL) + return NSD_ERROR; + + winbindd_free_response(&response); + + nsd_logprintf(NSD_LOG_MIN, " %s\n", result); + nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC); + return NSD_OK; + } + + case WINBINDD_GETGRNAM: + case WINBINDD_GETGRGID: + { + const struct winbindd_gr *gr = &response.data.gr; + const char * members; + + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) GETGRNAM | GETGRGID\n"); + + if (gr->num_gr_mem && response.extra_data.data) { + members = response.extra_data.data; + } else { + members = ""; + } + + rlen = asprintf(&result, "%s:%s:%d:%s\n", + gr->gr_name, gr->gr_passwd, gr->gr_gid, members); + if (rlen == 0 || result == NULL) + return NSD_ERROR; + + winbindd_free_response(&response); + + nsd_logprintf(NSD_LOG_MIN, " %s\n", result); + nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC); + return NSD_OK; + } + + case WINBINDD_SETGRENT: + case WINBINDD_SETPWENT: + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) SETGRENT | SETPWENT\n"); + winbindd_free_response(&response); + return(do_list(1,rq)); + + case WINBINDD_GETGRENT: + case WINBINDD_GETGRLST: + { + int entries; + + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) GETGRENT | GETGRLIST %d responses\n", + response.data.num_entries); + + if (response.data.num_entries) { + const struct winbindd_gr *gr = &response.data.gr; + const char * members; + fstring grp_name; + int i; + + gr = (struct winbindd_gr *)response.extra_data.data; + if (! gr ) { + nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); + winbindd_free_response(&response); + return NSD_ERROR; + } + + members = (char *)response.extra_data.data + + (response.data.num_entries * sizeof(struct winbindd_gr)); + + for (i = 0; i < response.data.num_entries; i++) { + snprintf(grp_name, sizeof(grp_name) - 1, "%s:%s:%d:", + gr->gr_name, gr->gr_passwd, gr->gr_gid); + + nsd_append_element(rq, NS_SUCCESS, result, rlen); + nsd_append_result(rq, NS_SUCCESS, + &members[gr->gr_mem_ofs], + strlen(&members[gr->gr_mem_ofs])); + + /* Don't log the whole list, because it might be + * _really_ long and we probably don't want to clobber + * the log with it. + */ + nsd_logprintf(NSD_LOG_MIN, " %s (...)\n", grp_name); + + gr++; + } + } + + entries = response.data.num_entries; + winbindd_free_response(&response); + if (entries < MAX_GETPWENT_USERS) + return(do_list(2,rq)); + else + return(do_list(1,rq)); + } + + case WINBINDD_GETPWENT: + { + int entries; + + nsd_logprintf(NSD_LOG_MIN, + "callback (winbind) GETPWENT %d responses\n", + response.data.num_entries); + + if (response.data.num_entries) { + struct winbindd_pw *pw = &response.data.pw; + int i; + + pw = (struct winbindd_pw *)response.extra_data.data; + if (! pw ) { + nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); + winbindd_free_response(&response); + return NSD_ERROR; + } + for (i = 0; i < response.data.num_entries; i++) { + result = NULL; + rlen = asprintf(&result, "%s:%s:%d:%d:%s:%s:%s", + pw->pw_name, + pw->pw_passwd, + pw->pw_uid, + pw->pw_gid, + pw->pw_gecos, + pw->pw_dir, + pw->pw_shell); + + if (rlen != 0 && result != NULL) { + nsd_logprintf(NSD_LOG_MIN, " %s\n",result); + nsd_append_element(rq, NS_SUCCESS, result, rlen); + free(result); + } + + pw++; + } + } + + entries = response.data.num_entries; + winbindd_free_response(&response); + if (entries < MAX_GETPWENT_USERS) + return(do_list(2,rq)); + else + return(do_list(1,rq)); + } + + case WINBINDD_ENDGRENT: + case WINBINDD_ENDPWENT: + nsd_logprintf(NSD_LOG_MIN, "callback (winbind) ENDGRENT | ENDPWENT\n"); + nsd_append_element(rq, NS_SUCCESS, "\n", 1); + winbindd_free_response(&response); + return NSD_NEXT; + + default: + winbindd_free_response(&response); + nsd_logprintf(NSD_LOG_MIN, "callback (winbind) invalid command %d\n", (int)rq->f_cmd_data); + return NSD_NEXT; + } +} + +static int +winbind_timeout(nsd_file_t **rqp, nsd_times_t *to) +{ + nsd_file_t *rq; + + dequeue_request(); + + nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n"); + + rq = to->t_file; + *rqp = rq; + + /* Remove the callback and timeout */ + nsd_callback_remove(winbindd_fd); + nsd_timeout_remove(rq); + + rq->f_status = NS_NOTFOUND; + return NSD_NEXT; +} + +static int +send_next_request(nsd_file_t *rq, struct winbindd_request *request) +{ + NSS_STATUS status; + long timeout; + + switch (rq->f_index) { + case LOOKUP: + timeout = nsd_attr_fetch_long(rq->f_attrs, + "lookup_timeout", 10, 10); + break; + case LIST: + timeout = nsd_attr_fetch_long(rq->f_attrs, + "list_timeout", 10, 10); + break; + default: + nsd_logprintf(NSD_LOG_OPER, + "send_next_request (winbind) " + "invalid request type %d\n", rq->f_index); + rq->f_status = NS_BADREQ; + return NSD_NEXT; + } + + nsd_logprintf(NSD_LOG_MIN, + "send_next_request (winbind) %d, timeout = %d sec\n", + rq->f_cmd_data, timeout); + status = winbindd_send_request((int)rq->f_cmd_data,0,request); + SAFE_FREE(request); + + if (status != NSS_STATUS_SUCCESS) { + nsd_logprintf(NSD_LOG_MIN, + "send_next_request (winbind) error status = %d\n", + status); + rq->f_status = status; + return NSD_NEXT; + } + + current_rq = rq; + + /* + * Set up callback and timeouts + */ + nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n", + winbindd_fd); + + nsd_callback_new(winbindd_fd, winbind_callback, NSD_READ); + nsd_timeout_new(rq, timeout * 1000, winbind_timeout, NULL); + return NSD_CONTINUE; +} + +int init(void) +{ + nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n"); + return(NSD_OK); +} + +int lookup(nsd_file_t *rq) +{ + char *map; + char *key; + struct winbindd_request *request; + + nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n"); + if (! rq) + return NSD_ERROR; + + map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); + key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); + if (! map || ! key) { + nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n"); + rq->f_status = NS_BADREQ; + return NSD_ERROR; + } + + nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map); + + request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); + if (! request) { + nsd_logprintf(NSD_LOG_RESOURCE, + "lookup (winbind): failed malloc\n"); + return NSD_ERROR; + } + + if (strcasecmp(map,"passwd.byuid") == 0) { + request->data.uid = atoi(key); + rq->f_cmd_data = (void *)WINBINDD_GETPWUID; + } else if (strcasecmp(map,"passwd.byname") == 0) { + strncpy(request->data.username, key, + sizeof(request->data.username) - 1); + request->data.username[sizeof(request->data.username) - 1] = '\0'; + rq->f_cmd_data = (void *)WINBINDD_GETPWNAM; + } else if (strcasecmp(map,"group.byname") == 0) { + strncpy(request->data.groupname, key, + sizeof(request->data.groupname) - 1); + request->data.groupname[sizeof(request->data.groupname) - 1] = '\0'; + rq->f_cmd_data = (void *)WINBINDD_GETGRNAM; + } else if (strcasecmp(map,"group.bygid") == 0) { + request->data.gid = atoi(key); + rq->f_cmd_data = (void *)WINBINDD_GETGRGID; + } else if (strcasecmp(map,"hosts.byname") == 0) { + strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); + request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; + rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME; + } else if (strcasecmp(map,"hosts.byaddr") == 0) { + strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); + request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; + rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP; + } else { + /* + * Don't understand this map - just return not found + */ + nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n"); + SAFE_FREE(request); + rq->f_status = NS_NOTFOUND; + return NSD_NEXT; + } + + return(do_request(rq, request)); +} + +int list(nsd_file_t *rq) +{ + char *map; + + nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n"); + if (! rq) + return NSD_ERROR; + + map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); + if (! map ) { + nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n"); + rq->f_status = NS_BADREQ; + return NSD_ERROR; + } + + nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map); + + return (do_list(0,rq)); +} + +static int +do_list(int state, nsd_file_t *rq) +{ + char *map; + struct winbindd_request *request; + + nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state); + + map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); + request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); + if (! request) { + nsd_logprintf(NSD_LOG_RESOURCE, + "do_list (winbind): failed malloc\n"); + return NSD_ERROR; + } + + if (strcasecmp(map,"passwd.byname") == 0) { + switch (state) { + case 0: + rq->f_cmd_data = (void *)WINBINDD_SETPWENT; + break; + case 1: + request->data.num_entries = MAX_GETPWENT_USERS; + rq->f_cmd_data = (void *)WINBINDD_GETPWENT; + break; + case 2: + rq->f_cmd_data = (void *)WINBINDD_ENDPWENT; + break; + default: + nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); + SAFE_FREE(request); + rq->f_status = NS_NOTFOUND; + return NSD_NEXT; + } + } else if (strcasecmp(map,"group.byname") == 0) { + switch (state) { + case 0: + rq->f_cmd_data = (void *)WINBINDD_SETGRENT; + break; + case 1: + request->data.num_entries = MAX_GETGRENT_USERS; + rq->f_cmd_data = (void *)WINBINDD_GETGRENT; + break; + case 2: + rq->f_cmd_data = (void *)WINBINDD_ENDGRENT; + break; + default: + nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); + SAFE_FREE(request); + rq->f_status = NS_NOTFOUND; + return NSD_NEXT; + } + } else { + /* + * Don't understand this map - just return not found + */ + nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n"); + SAFE_FREE(request); + rq->f_status = NS_NOTFOUND; + return NSD_NEXT; + } + + return(do_request(rq, request)); +} + +#endif /* HAVE_NS_API_H */ diff --git a/nsswitch/winbind_nss_irix.h b/nsswitch/winbind_nss_irix.h new file mode 100644 index 0000000000..b47d23e204 --- /dev/null +++ b/nsswitch/winbind_nss_irix.h @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WINBIND_NSS_IRIX_H +#define _WINBIND_NSS_IRIX_H + +/* following required to prevent warnings of double definition + * of datum from ns_api.h +*/ +#ifdef DATUM +#define _DATUM_DEFINED +#endif + +#include + +typedef enum +{ + NSS_STATUS_SUCCESS=NS_SUCCESS, + NSS_STATUS_NOTFOUND=NS_NOTFOUND, + NSS_STATUS_UNAVAIL=NS_UNAVAIL, + NSS_STATUS_TRYAGAIN=NS_TRYAGAIN +} NSS_STATUS; + +#endif /* _WINBIND_NSS_IRIX_H */ diff --git a/nsswitch/winbind_nss_linux.c b/nsswitch/winbind_nss_linux.c new file mode 100644 index 0000000000..2b51a8e15d --- /dev/null +++ b/nsswitch/winbind_nss_linux.c @@ -0,0 +1,1477 @@ +/* + Unix SMB/CIFS implementation. + + Windows NT Domain nsswitch module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "winbind_client.h" + +#if HAVE_PTHREAD_H +#include +#endif + +#if HAVE_PTHREAD +static pthread_mutex_t winbind_nss_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/* Maximum number of users to pass back over the unix domain socket + per call. This is not a static limit on the total number of users + or groups returned in total. */ + +#define MAX_GETPWENT_USERS 250 +#define MAX_GETGRENT_USERS 250 + +NSS_STATUS _nss_winbind_setpwent(void); +NSS_STATUS _nss_winbind_endpwent(void); +NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_setgrent(void); +NSS_STATUS _nss_winbind_endgrent(void); +NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, + char *buffer, size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, + long int *size, gid_t **groups, + long int limit, int *errnop); +NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, + int *num_groups, char *buffer, size_t buf_size, + int *errnop); +NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); +NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); +NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, + size_t buflen, int *errnop); + +/* Prototypes from wb_common.c */ + +/* Allocate some space from the nss static buffer. The buffer and buflen + are the pointers passed in by the C library to the _nss_ntdom_* + functions. */ + +static char *get_static(char **buffer, size_t *buflen, size_t len) +{ + char *result; + + /* Error check. We return false if things aren't set up right, or + there isn't enough buffer space left. */ + + if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { + return NULL; + } + + /* Return an index into the static buffer */ + + result = *buffer; + *buffer += len; + *buflen -= len; + + return result; +} + +/* I've copied the strtok() replacement function next_token_Xalloc() from + lib/util_str.c as I really don't want to have to link in any other + objects if I can possibly avoid it. */ + +static bool next_token_alloc(const char **ptr, + char **pp_buff, + const char *sep) +{ + char *s; + char *saved_s; + char *pbuf; + bool quoted; + size_t len=1; + + *pp_buff = NULL; + if (!ptr) { + return(false); + } + + s = (char *)*ptr; + + /* default to simple separators */ + if (!sep) { + sep = " \t\n\r"; + } + + /* find the first non sep char */ + while (*s && strchr(sep,*s)) { + s++; + } + + /* nothing left? */ + if (!*s) { + return false; + } + + /* When restarting we need to go from here. */ + saved_s = s; + + /* Work out the length needed. */ + for (quoted = false; *s && + (quoted || !strchr(sep,*s)); s++) { + if (*s == '\"') { + quoted = !quoted; + } else { + len++; + } + } + + /* We started with len = 1 so we have space for the nul. */ + *pp_buff = (char *)malloc(len); + if (!*pp_buff) { + return false; + } + + /* copy over the token */ + pbuf = *pp_buff; + s = saved_s; + for (quoted = false; *s && + (quoted || !strchr(sep,*s)); s++) { + if ( *s == '\"' ) { + quoted = !quoted; + } else { + *pbuf++ = *s; + } + } + + *ptr = (*s) ? s+1 : s; + *pbuf = 0; + + return true; +} + +/* Fill a pwent structure from a winbindd_response structure. We use + the static data passed to us by libc to put strings and stuff in. + Return NSS_STATUS_TRYAGAIN if we run out of memory. */ + +static NSS_STATUS fill_pwent(struct passwd *result, + struct winbindd_pw *pw, + char **buffer, size_t *buflen) +{ + /* User name */ + + if ((result->pw_name = + get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->pw_name, pw->pw_name); + + /* Password */ + + if ((result->pw_passwd = + get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->pw_passwd, pw->pw_passwd); + + /* [ug]id */ + + result->pw_uid = pw->pw_uid; + result->pw_gid = pw->pw_gid; + + /* GECOS */ + + if ((result->pw_gecos = + get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->pw_gecos, pw->pw_gecos); + + /* Home directory */ + + if ((result->pw_dir = + get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->pw_dir, pw->pw_dir); + + /* Logon shell */ + + if ((result->pw_shell = + get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->pw_shell, pw->pw_shell); + + /* The struct passwd for Solaris has some extra fields which must + be initialised or nscd crashes. */ + +#if HAVE_PASSWD_PW_COMMENT + result->pw_comment = ""; +#endif + +#if HAVE_PASSWD_PW_AGE + result->pw_age = ""; +#endif + + return NSS_STATUS_SUCCESS; +} + +/* Fill a grent structure from a winbindd_response structure. We use + the static data passed to us by libc to put strings and stuff in. + Return NSS_STATUS_TRYAGAIN if we run out of memory. */ + +static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, + char *gr_mem, char **buffer, size_t *buflen) +{ + char *name; + int i; + char *tst; + + /* Group name */ + + if ((result->gr_name = + get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->gr_name, gr->gr_name); + + /* Password */ + + if ((result->gr_passwd = + get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) { + + /* Out of memory */ + return NSS_STATUS_TRYAGAIN; + } + + strcpy(result->gr_passwd, gr->gr_passwd); + + /* gid */ + + result->gr_gid = gr->gr_gid; + + /* Group membership */ + + if ((gr->num_gr_mem < 0) || !gr_mem) { + gr->num_gr_mem = 0; + } + + /* this next value is a pointer to a pointer so let's align it */ + + /* Calculate number of extra bytes needed to align on pointer size boundry */ + if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0) + i = sizeof(char*) - i; + + if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * + sizeof(char *)+i))) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + result->gr_mem = (char **)(tst + i); + + if (gr->num_gr_mem == 0) { + + /* Group is empty */ + + *(result->gr_mem) = NULL; + return NSS_STATUS_SUCCESS; + } + + /* Start looking at extra data */ + + i = 0; + + while(next_token_alloc((const char **)&gr_mem, &name, ",")) { + /* Allocate space for member */ + if (((result->gr_mem)[i] = + get_static(buffer, buflen, strlen(name) + 1)) == NULL) { + free(name); + /* Out of memory */ + return NSS_STATUS_TRYAGAIN; + } + strcpy((result->gr_mem)[i], name); + free(name); + i++; + } + + /* Terminate list */ + + (result->gr_mem)[i] = NULL; + + return NSS_STATUS_SUCCESS; +} + +/* + * NSS user functions + */ + +static struct winbindd_response getpwent_response; + +static int ndx_pw_cache; /* Current index into pwd cache */ +static int num_pw_cache; /* Current size of pwd cache */ + +/* Rewind "file pointer" to start of ntdom password database */ + +NSS_STATUS +_nss_winbind_setpwent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setpwent\n", getpid()); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + if (num_pw_cache > 0) { + ndx_pw_cache = num_pw_cache = 0; + winbindd_free_response(&getpwent_response); + } + + ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + return ret; +} + +/* Close ntdom password database "file pointer" */ + +NSS_STATUS +_nss_winbind_endpwent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endpwent\n", getpid()); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + if (num_pw_cache > 0) { + ndx_pw_cache = num_pw_cache = 0; + winbindd_free_response(&getpwent_response); + } + + ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* Fetch the next password entry from ntdom password database */ + +NSS_STATUS +_nss_winbind_getpwent_r(struct passwd *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + static int called_again; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwent\n", getpid()); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + /* Return an entry from the cache if we have one, or if we are + called again because we exceeded our static buffer. */ + + if ((ndx_pw_cache < num_pw_cache) || called_again) { + goto return_result; + } + + /* Else call winbindd to get a bunch of entries */ + + if (num_pw_cache > 0) { + winbindd_free_response(&getpwent_response); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(getpwent_response); + + request.data.num_entries = MAX_GETPWENT_USERS; + + ret = winbindd_request_response(WINBINDD_GETPWENT, &request, + &getpwent_response); + + if (ret == NSS_STATUS_SUCCESS) { + struct winbindd_pw *pw_cache; + + /* Fill cache */ + + ndx_pw_cache = 0; + num_pw_cache = getpwent_response.data.num_entries; + + /* Return a result */ + + return_result: + + pw_cache = (struct winbindd_pw *) + getpwent_response.extra_data.data; + + /* Check data is valid */ + + if (pw_cache == NULL) { + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + ret = fill_pwent(result, &pw_cache[ndx_pw_cache], + &buffer, &buflen); + + /* Out of memory - try again */ + + if (ret == NSS_STATUS_TRYAGAIN) { + called_again = true; + *errnop = errno = ERANGE; + goto done; + } + + *errnop = errno = 0; + called_again = false; + ndx_pw_cache++; + + /* If we've finished with this lot of results free cache */ + + if (ndx_pw_cache == num_pw_cache) { + ndx_pw_cache = num_pw_cache = 0; + winbindd_free_response(&getpwent_response); + } + } + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + return ret; +} + +/* Return passwd struct from uid */ + +NSS_STATUS +_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwuid_r %d\n", getpid(), (unsigned int)uid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + /* If our static buffer needs to be expanded we are called again */ + if (!keep_response || uid != response.data.pw.pw_uid) { + + /* Call for the first time */ + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.uid = uid; + + ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + ret = fill_pwent(result, &response.data.pw, + &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + *errnop = errno = ERANGE; + goto done; + } + + keep_response = false; + *errnop = errno = 0; + } + + winbindd_free_response(&response); + + done: + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(), + (unsigned int)uid, nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* Return passwd struct from username */ +NSS_STATUS +_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwnam_r %s\n", getpid(), name); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + /* If our static buffer needs to be expanded we are called again */ + + if (!keep_response || strcmp(name,response.data.pw.pw_name) != 0) { + + /* Call for the first time */ + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + strncpy(request.data.username, name, + sizeof(request.data.username) - 1); + request.data.username + [sizeof(request.data.username) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + ret = fill_pwent(result, &response.data.pw, &buffer, + &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = false; + *errnop = errno = 0; + } + + winbindd_free_response(&response); + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(), + name, nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* + * NSS group functions + */ + +static struct winbindd_response getgrent_response; + +static int ndx_gr_cache; /* Current index into grp cache */ +static int num_gr_cache; /* Current size of grp cache */ + +/* Rewind "file pointer" to start of ntdom group database */ + +NSS_STATUS +_nss_winbind_setgrent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setgrent\n", getpid()); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + if (num_gr_cache > 0) { + ndx_gr_cache = num_gr_cache = 0; + winbindd_free_response(&getgrent_response); + } + + ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* Close "file pointer" for ntdom group database */ + +NSS_STATUS +_nss_winbind_endgrent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endgrent\n", getpid()); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + if (num_gr_cache > 0) { + ndx_gr_cache = num_gr_cache = 0; + winbindd_free_response(&getgrent_response); + } + + ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* Get next entry from ntdom group database */ + +static NSS_STATUS +winbind_getgrent(enum winbindd_cmd cmd, + struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_request request; + static int called_again; + + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrent\n", getpid()); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + /* Return an entry from the cache if we have one, or if we are + called again because we exceeded our static buffer. */ + + if ((ndx_gr_cache < num_gr_cache) || called_again) { + goto return_result; + } + + /* Else call winbindd to get a bunch of entries */ + + if (num_gr_cache > 0) { + winbindd_free_response(&getgrent_response); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(getgrent_response); + + request.data.num_entries = MAX_GETGRENT_USERS; + + ret = winbindd_request_response(cmd, &request, + &getgrent_response); + + if (ret == NSS_STATUS_SUCCESS) { + struct winbindd_gr *gr_cache; + int mem_ofs; + + /* Fill cache */ + + ndx_gr_cache = 0; + num_gr_cache = getgrent_response.data.num_entries; + + /* Return a result */ + + return_result: + + gr_cache = (struct winbindd_gr *) + getgrent_response.extra_data.data; + + /* Check data is valid */ + + if (gr_cache == NULL) { + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + /* Fill group membership. The offset into the extra data + for the group membership is the reported offset plus the + size of all the winbindd_gr records returned. */ + + mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + + num_gr_cache * sizeof(struct winbindd_gr); + + ret = fill_grent(result, &gr_cache[ndx_gr_cache], + ((char *)getgrent_response.extra_data.data)+mem_ofs, + &buffer, &buflen); + + /* Out of memory - try again */ + + if (ret == NSS_STATUS_TRYAGAIN) { + called_again = true; + *errnop = errno = ERANGE; + goto done; + } + + *errnop = 0; + called_again = false; + ndx_gr_cache++; + + /* If we've finished with this lot of results free cache */ + + if (ndx_gr_cache == num_gr_cache) { + ndx_gr_cache = num_gr_cache = 0; + winbindd_free_response(&getgrent_response); + } + } + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + + +NSS_STATUS +_nss_winbind_getgrent_r(struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); +} + +NSS_STATUS +_nss_winbind_getgrlst_r(struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); +} + +/* Return group struct from group name */ + +NSS_STATUS +_nss_winbind_getgrnam_r(const char *name, + struct group *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + /* If our static buffer needs to be expanded we are called again */ + /* Or if the stored response group name differs from the request. */ + + if (!keep_response || strcmp(name,response.data.gr.gr_name) != 0) { + + /* Call for the first time */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.groupname, name, + sizeof(request.data.groupname)); + request.data.groupname + [sizeof(request.data.groupname) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, + &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, &buffer, + &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = false; + *errnop = 0; + } + + winbindd_free_response(&response); + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(), + name, nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* Return group struct from gid */ + +NSS_STATUS +_nss_winbind_getgrgid_r(gid_t gid, + struct group *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + /* If our static buffer needs to be expanded we are called again */ + /* Or if the stored response group name differs from the request. */ + + if (!keep_response || gid != response.data.gr.gr_gid) { + + /* Call for the first time */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.gid = gid; + + ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, + &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, &buffer, + &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = true; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = false; + *errnop = 0; + } + + winbindd_free_response(&response); + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(), + (unsigned int)gid, nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + return ret; +} + +/* Initialise supplementary groups */ + +NSS_STATUS +_nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, + long int *size, gid_t **groups, long int limit, + int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + int i; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), + user, group); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.username, user, + sizeof(request.data.username) - 1); + + ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + int num_gids = response.data.num_entries; + gid_t *gid_list = (gid_t *)response.extra_data.data; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS " + "and %d gids\n", getpid(), + user, num_gids); +#endif + if (gid_list == NULL) { + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + /* Copy group list to client */ + + for (i = 0; i < num_gids; i++) { + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s (%d): " + "processing gid %d \n", getpid(), + user, group, gid_list[i]); +#endif + + /* Skip primary group */ + + if (gid_list[i] == group) { + continue; + } + + /* Filled buffer ? If so, resize. */ + + if (*start == *size) { + long int newsize; + gid_t *newgroups; + + newsize = 2 * (*size); + if (limit > 0) { + if (*size == limit) { + goto done; + } + if (newsize > limit) { + newsize = limit; + } + } + + newgroups = (gid_t *) + realloc((*groups), + newsize * sizeof(**groups)); + if (!newgroups) { + *errnop = ENOMEM; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + *groups = newgroups; + *size = newsize; + } + + /* Add to buffer */ + + (*groups)[*start] = gid_list[i]; + *start += 1; + } + } + + /* Back to your regularly scheduled programming */ + + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(), + user, nss_err_str(ret), ret); +#endif + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + + +/* return a list of group SIDs for a user SID */ +NSS_STATUS +_nss_winbind_getusersids(const char *user_sid, char **group_sids, + int *num_groups, + char *buffer, size_t buf_size, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response); + + if (ret != NSS_STATUS_SUCCESS) { + goto done; + } + + if (buf_size < response.length - sizeof(response)) { + ret = NSS_STATUS_TRYAGAIN; + errno = *errnop = ERANGE; + goto done; + } + + *num_groups = response.data.num_entries; + *group_sids = buffer; + memcpy(buffer, response.extra_data.data, response.length - sizeof(response)); + errno = *errnop = 0; + + done: + winbindd_free_response(&response); + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + + +/* map a user or group name to a SID string */ +NSS_STATUS +_nss_winbind_nametosid(const char *name, char **sid, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + strncpy(request.data.name.name, name, + sizeof(request.data.name.name) - 1); + request.data.name.name[sizeof(request.data.name.name) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strcpy(*sid, response.data.sid.sid); + +failed: + winbindd_free_response(&response); + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* map a sid string to a user or group name */ +NSS_STATUS +_nss_winbind_sidtoname(const char *sid, char **name, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + static char sep_char; + unsigned needed; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + /* we need to fetch the separator first time through */ + if (!sep_char) { + ret = winbindd_request_response(WINBINDD_INFO, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + sep_char = response.data.info.winbind_separator; + winbindd_free_response(&response); + } + + + strncpy(request.data.sid, sid, + sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + needed = + strlen(response.data.name.dom_name) + + strlen(response.data.name.name) + 2; + + if (buflen < needed) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + snprintf(buffer, needed, "%s%c%s", + response.data.name.dom_name, + sep_char, + response.data.name.name); + + *name = buffer; + *errnop = errno = 0; + +failed: + winbindd_free_response(&response); + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* map a sid to a uid */ +NSS_STATUS +_nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + *uid = response.data.uid; + +failed: + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* map a sid to a gid */ +NSS_STATUS +_nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + *gid = response.data.gid; + +failed: + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* map a uid to a SID string */ +NSS_STATUS +_nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.uid = uid; + + ret = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strcpy(*sid, response.data.sid.sid); + +failed: + winbindd_free_response(&response); + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} + +/* map a gid to a SID string */ +NSS_STATUS +_nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid); +#endif + +#if HAVE_PTHREAD + pthread_mutex_lock(&winbind_nss_mutex); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.gid = gid; + + ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strcpy(*sid, response.data.sid.sid); + +failed: + winbindd_free_response(&response); + +#if HAVE_PTHREAD + pthread_mutex_unlock(&winbind_nss_mutex); +#endif + + return ret; +} diff --git a/nsswitch/winbind_nss_linux.h b/nsswitch/winbind_nss_linux.h new file mode 100644 index 0000000000..db5a378aad --- /dev/null +++ b/nsswitch/winbind_nss_linux.h @@ -0,0 +1,29 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WINBIND_NSS_LINUX_H +#define _WINBIND_NSS_LINUX_H + +#include + +typedef enum nss_status NSS_STATUS; + +#endif /* _WINBIND_NSS_LINUX_H */ diff --git a/nsswitch/winbind_nss_netbsd.c b/nsswitch/winbind_nss_netbsd.c new file mode 100644 index 0000000000..9b8e0a2265 --- /dev/null +++ b/nsswitch/winbind_nss_netbsd.c @@ -0,0 +1,442 @@ +/* + Unix SMB/CIFS implementation. + + NetBSD loadable authentication module, providing identification + routines against Samba winbind/Windows NT Domain + + Copyright (C) Luke Mewburn 2004-2005 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + + +#include "winbind_client.h" + +#include +#include +#include + + /* dynamic nsswitch with "new" getpw* nsdispatch API available */ +#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R) + +/* + group functions + --------------- +*/ + +static struct group _winbind_group; +static char _winbind_groupbuf[1024]; + +/* + * We need a proper prototype for this :-) + */ + +NSS_STATUS _nss_winbind_setpwent(void); +NSS_STATUS _nss_winbind_endpwent(void); +NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_setgrent(void); +NSS_STATUS _nss_winbind_endgrent(void); +NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, + char *buffer, size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, + long int *size, gid_t **groups, + long int limit, int *errnop); +NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, + int *num_groups, char *buffer, size_t buf_size, + int *errnop); +NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); +NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); +NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, + size_t buflen, int *errnop); + +int +netbsdwinbind_endgrent(void *nsrv, void *nscb, va_list ap) +{ + int rv; + + rv = _nss_winbind_endgrent(); + return rv; +} + +int +netbsdwinbind_setgrent(void *nsrv, void *nscb, va_list ap) +{ + int rv; + + rv = _nss_winbind_setgrent(); + return rv; +} + +int +netbsdwinbind_getgrent(void *nsrv, void *nscb, va_list ap) +{ + struct group **retval = va_arg(ap, struct group **); + + int rv, rerrno; + + *retval = NULL; + rv = _nss_winbind_getgrent_r(&_winbind_group, + _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno); + if (rv == NS_SUCCESS) + *retval = &_winbind_group; + return rv; +} + +int +netbsdwinbind_getgrent_r(void *nsrv, void *nscb, va_list ap) +{ + int *retval = va_arg(ap, int *); + struct group *grp = va_arg(ap, struct group *); + char *buffer = va_arg(ap, char *); + size_t buflen = va_arg(ap, size_t); + struct group **result = va_arg(ap, struct group **); + + int rv, rerrno; + + *result = NULL; + rerrno = 0; + + rv = _nss_winbind_getgrent_r(grp, buffer, buflen, rerrno); + if (rv == NS_SUCCESS) + *result = grp; + else + *retval = rerrno; + return rv; +} + +int +netbsdwinbind_getgrgid(void *nsrv, void *nscb, va_list ap) +{ + struct group **retval = va_arg(ap, struct group **); + gid_t gid = va_arg(ap, gid_t); + + int rv, rerrno; + + *retval = NULL; + rv = _nss_winbind_getgrgid_r(gid, &_winbind_group, + _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno); + if (rv == NS_SUCCESS) + *retval = &_winbind_group; + return rv; +} + +int +netbsdwinbind_getgrgid_r(void *nsrv, void *nscb, va_list ap) +{ + int *retval = va_arg(ap, int *); + gid_t gid = va_arg(ap, gid_t); + struct group *grp = va_arg(ap, struct group *); + char *buffer = va_arg(ap, char *); + size_t buflen = va_arg(ap, size_t); + struct group **result = va_arg(ap, struct group **); + + int rv, rerrno; + + *result = NULL; + rerrno = 0; + + rv = _nss_winbind_getgrgid_r(gid, grp, buffer, buflen, &rerrno); + if (rv == NS_SUCCESS) + *result = grp; + else + *retval = rerrno; + return rv; +} + +int +netbsdwinbind_getgrnam(void *nsrv, void *nscb, va_list ap) +{ + struct group **retval = va_arg(ap, struct group **); + const char *name = va_arg(ap, const char *); + + int rv, rerrno; + + *retval = NULL; + rv = _nss_winbind_getgrnam_r(name, &_winbind_group, + _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno); + if (rv == NS_SUCCESS) + *retval = &_winbind_group; + return rv; +} + +int +netbsdwinbind_getgrnam_r(void *nsrv, void *nscb, va_list ap) +{ + int *retval = va_arg(ap, int *); + const char *name = va_arg(ap, const char *); + struct group *grp = va_arg(ap, struct group *); + char *buffer = va_arg(ap, char *); + size_t buflen = va_arg(ap, size_t); + struct group **result = va_arg(ap, struct group **); + + int rv, rerrno; + + *result = NULL; + rerrno = 0; + + rv = _nss_winbind_getgrnam_r(name, grp, buffer, buflen, &rerrno); + if (rv == NS_SUCCESS) + *result = grp; + else + *retval = rerrno; + return rv; +} + +int +netbsdwinbind_getgroupmembership(void *nsrv, void *nscb, va_list ap) +{ + int *result = va_arg(ap, int *); + const char *uname = va_arg(ap, const char *); + gid_t agroup = va_arg(ap, gid_t); + gid_t *groups = va_arg(ap, gid_t *); + int maxgrp = va_arg(ap, int); + int *groupc = va_arg(ap, int *); + + struct winbindd_request request; + struct winbindd_response response; + gid_t *wblistv; + int wblistc, i, isdup, dupc; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + strncpy(request.data.username, uname, + sizeof(request.data.username) - 1); + i = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); + if (i != NSS_STATUS_SUCCESS) + return NS_NOTFOUND; + wblistv = (gid_t *)response.extra_data.data; + wblistc = response.data.num_entries; + + for (i = 0; i < wblistc; i++) { /* add winbind gids */ + isdup = 0; /* skip duplicates */ + for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) { + if (groups[dupc] == wblistv[i]) { + isdup = 1; + break; + } + } + if (isdup) + continue; + if (*groupc < maxgrp) /* add this gid */ + groups[*groupc] = wblistv[i]; + else + *result = -1; + (*groupc)++; + } + SAFE_FREE(wblistv); + return NS_NOTFOUND; +} + + +/* + passwd functions + ---------------- +*/ + +static struct passwd _winbind_passwd; +static char _winbind_passwdbuf[1024]; + +int +netbsdwinbind_endpwent(void *nsrv, void *nscb, va_list ap) +{ + int rv; + + rv = _nss_winbind_endpwent(); + return rv; +} + +int +netbsdwinbind_setpwent(void *nsrv, void *nscb, va_list ap) +{ + int rv; + + rv = _nss_winbind_setpwent(); + return rv; +} + +int +netbsdwinbind_getpwent(void *nsrv, void *nscb, va_list ap) +{ + struct passwd **retval = va_arg(ap, struct passwd **); + + int rv, rerrno; + + *retval = NULL; + + rv = _nss_winbind_getpwent_r(&_winbind_passwd, + _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno); + if (rv == NS_SUCCESS) + *retval = &_winbind_passwd; + return rv; +} + +int +netbsdwinbind_getpwent_r(void *nsrv, void *nscb, va_list ap) +{ + int *retval = va_arg(ap, int *); + struct passwd *pw = va_arg(ap, struct passwd *); + char *buffer = va_arg(ap, char *); + size_t buflen = va_arg(ap, size_t); + struct passwd **result = va_arg(ap, struct passwd **); + + int rv, rerrno; + + *result = NULL; + rerrno = 0; + + rv = _nss_winbind_getpwent_r(pw, buffer, buflen, rerrno); + if (rv == NS_SUCCESS) + *result = pw; + else + *retval = rerrno; + return rv; +} + +int +netbsdwinbind_getpwnam(void *nsrv, void *nscb, va_list ap) +{ + struct passwd **retval = va_arg(ap, struct passwd **); + const char *name = va_arg(ap, const char *); + + int rv, rerrno; + + *retval = NULL; + rv = _nss_winbind_getpwnam_r(name, &_winbind_passwd, + _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno); + if (rv == NS_SUCCESS) + *retval = &_winbind_passwd; + return rv; +} + +int +netbsdwinbind_getpwnam_r(void *nsrv, void *nscb, va_list ap) +{ + int *retval = va_arg(ap, int *); + const char *name = va_arg(ap, const char *); + struct passwd *pw = va_arg(ap, struct passwd *); + char *buffer = va_arg(ap, char *); + size_t buflen = va_arg(ap, size_t); + struct passwd **result = va_arg(ap, struct passwd **); + + int rv, rerrno; + + *result = NULL; + rerrno = 0; + + rv = _nss_winbind_getpwnam_r(name, pw, buffer, buflen, &rerrno); + if (rv == NS_SUCCESS) + *result = pw; + else + *retval = rerrno; + return rv; +} + +int +netbsdwinbind_getpwuid(void *nsrv, void *nscb, va_list ap) +{ + struct passwd **retval = va_arg(ap, struct passwd **); + uid_t uid = va_arg(ap, uid_t); + + int rv, rerrno; + + *retval = NULL; + rv = _nss_winbind_getpwuid_r(uid, &_winbind_passwd, + _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno); + if (rv == NS_SUCCESS) + *retval = &_winbind_passwd; + return rv; +} + +int +netbsdwinbind_getpwuid_r(void *nsrv, void *nscb, va_list ap) +{ + int *retval = va_arg(ap, int *); + uid_t uid = va_arg(ap, uid_t); + struct passwd *pw = va_arg(ap, struct passwd *); + char *buffer = va_arg(ap, char *); + size_t buflen = va_arg(ap, size_t); + struct passwd **result = va_arg(ap, struct passwd **); + + int rv, rerrno; + + *result = NULL; + rerrno = 0; + + rv = _nss_winbind_getpwuid_r(uid, pw, buffer, buflen, &rerrno); + if (rv == NS_SUCCESS) + *result = pw; + else + *retval = rerrno; + return rv; +} + + +/* + nsswitch module setup + --------------------- +*/ + + +static ns_mtab winbind_methods[] = { + +{ NSDB_GROUP, "endgrent", netbsdwinbind_endgrent, NULL }, +{ NSDB_GROUP, "getgrent", netbsdwinbind_getgrent, NULL }, +{ NSDB_GROUP, "getgrent_r", netbsdwinbind_getgrent_r, NULL }, +{ NSDB_GROUP, "getgrgid", netbsdwinbind_getgrgid, NULL }, +{ NSDB_GROUP, "getgrgid_r", netbsdwinbind_getgrgid_r, NULL }, +{ NSDB_GROUP, "getgrnam", netbsdwinbind_getgrnam, NULL }, +{ NSDB_GROUP, "getgrnam_r", netbsdwinbind_getgrnam_r, NULL }, +{ NSDB_GROUP, "setgrent", netbsdwinbind_setgrent, NULL }, +{ NSDB_GROUP, "setgroupent", netbsdwinbind_setgrent, NULL }, +{ NSDB_GROUP, "getgroupmembership", netbsdwinbind_getgroupmembership, NULL }, + +{ NSDB_PASSWD, "endpwent", netbsdwinbind_endpwent, NULL }, +{ NSDB_PASSWD, "getpwent", netbsdwinbind_getpwent, NULL }, +{ NSDB_PASSWD, "getpwent_r", netbsdwinbind_getpwent_r, NULL }, +{ NSDB_PASSWD, "getpwnam", netbsdwinbind_getpwnam, NULL }, +{ NSDB_PASSWD, "getpwnam_r", netbsdwinbind_getpwnam_r, NULL }, +{ NSDB_PASSWD, "getpwuid", netbsdwinbind_getpwuid, NULL }, +{ NSDB_PASSWD, "getpwuid_r", netbsdwinbind_getpwuid_r, NULL }, +{ NSDB_PASSWD, "setpassent", netbsdwinbind_setpwent, NULL }, +{ NSDB_PASSWD, "setpwent", netbsdwinbind_setpwent, NULL }, + +}; + +ns_mtab * +nss_module_register(const char *source, unsigned int *mtabsize, + nss_module_unregister_fn *unreg) +{ + *mtabsize = sizeof(winbind_methods)/sizeof(winbind_methods[0]); + *unreg = NULL; + return (winbind_methods); +} + +#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */ diff --git a/nsswitch/winbind_nss_netbsd.h b/nsswitch/winbind_nss_netbsd.h new file mode 100644 index 0000000000..5aeb2b9d7d --- /dev/null +++ b/nsswitch/winbind_nss_netbsd.h @@ -0,0 +1,40 @@ +/* + Unix SMB/CIFS implementation. + + NetBSD loadable authentication module, providing identification + routines against Samba winbind/Windows NT Domain + + Copyright (C) Luke Mewburn 2004-2005 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WINBIND_NSS_NETBSD_H +#define _WINBIND_NSS_NETBSD_H + +#include + + /* dynamic nsswitch with "new" getpw* nsdispatch API available */ +#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R) + +typedef int NSS_STATUS; + +#define NSS_STATUS_SUCCESS NS_SUCCESS +#define NSS_STATUS_NOTFOUND NS_NOTFOUND +#define NSS_STATUS_UNAVAIL NS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NS_TRYAGAIN + +#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */ + +#endif /* _WINBIND_NSS_NETBSD_H */ diff --git a/nsswitch/winbind_nss_solaris.c b/nsswitch/winbind_nss_solaris.c new file mode 100644 index 0000000000..4c85bd3621 --- /dev/null +++ b/nsswitch/winbind_nss_solaris.c @@ -0,0 +1,654 @@ +/* + Solaris NSS wrapper for winbind + - Shirish Kalele 2000 + + Based on Luke Howard's ldap_nss module for Solaris + */ + +/* + Copyright (C) 1997-2003 Luke Howard. + This file is part of the nss_ldap library. + + The nss_ldap library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + The nss_ldap library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the nss_ldap library; see the file COPYING.LIB. If not, + see . +*/ + +#undef DEVELOPER + +#include "winbind_client.h" +#include +#include +#include +#include +#include +#include "includes.h" +#include +#if !defined(HPUX) +#include +#endif /*hpux*/ + +#if defined(HAVE_NSS_COMMON_H) || defined(HPUX) + +#undef NSS_DEBUG + +#ifdef NSS_DEBUG +#define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str); +#else +#define NSS_DEBUG(str) ; +#endif + +#define NSS_ARGS(args) ((nss_XbyY_args_t *)args) + +#ifdef HPUX + +/* + * HP-UX 11 has no definiton of the nss_groupsbymem structure. This + * definition is taken from the nss_ldap project at: + * http://www.padl.com/OSS/nss_ldap.html + */ + +struct nss_groupsbymem { + const char *username; + gid_t *gid_array; + int maxgids; + int force_slow_way; + int (*str2ent)(const char *instr, int instr_len, void *ent, + char *buffer, int buflen); + nss_status_t (*process_cstr)(const char *instr, int instr_len, + struct nss_groupsbymem *); + int numgids; +}; + +#endif /* HPUX */ + +#define make_pwent_str(dest, src) \ +{ \ + if((dest = get_static(buffer, buflen, strlen(src)+1)) == NULL) \ + { \ + *errnop = ERANGE; \ + NSS_DEBUG("ERANGE error"); \ + return NSS_STATUS_TRYAGAIN; \ + } \ + strcpy(dest, src); \ +} + +static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args) +{ + NSS_DEBUG("_nss_winbind_setpwent_solwrap"); + return _nss_winbind_setpwent(); +} + +static NSS_STATUS +_nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args) +{ + NSS_DEBUG("_nss_winbind_endpwent_solwrap"); + return _nss_winbind_endpwent(); +} + +static NSS_STATUS +_nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args) +{ + NSS_STATUS ret; + char* buffer = NSS_ARGS(args)->buf.buffer; + int buflen = NSS_ARGS(args)->buf.buflen; + struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; + int* errnop = &NSS_ARGS(args)->erange; + char logmsg[80]; + + ret = _nss_winbind_getpwent_r(result, buffer, + buflen, errnop); + + if(ret == NSS_STATUS_SUCCESS) + { + snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n", + result->pw_name); + NSS_DEBUG(logmsg); + NSS_ARGS(args)->returnval = (void*) result; + } else { + snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret); + NSS_DEBUG(logmsg); + } + + return ret; +} + +static NSS_STATUS +_nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args) +{ + NSS_STATUS ret; + struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; + + NSS_DEBUG("_nss_winbind_getpwnam_solwrap"); + + ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name, + result, + NSS_ARGS(args)->buf.buffer, + NSS_ARGS(args)->buf.buflen, + &NSS_ARGS(args)->erange); + if(ret == NSS_STATUS_SUCCESS) + NSS_ARGS(args)->returnval = (void*) result; + + return ret; +} + +static NSS_STATUS +_nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args) +{ + NSS_STATUS ret; + struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; + + NSS_DEBUG("_nss_winbind_getpwuid_solwrap"); + ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid, + result, + NSS_ARGS(args)->buf.buffer, + NSS_ARGS(args)->buf.buflen, + &NSS_ARGS(args)->erange); + if(ret == NSS_STATUS_SUCCESS) + NSS_ARGS(args)->returnval = (void*) result; + + return ret; +} + +static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args) +{ + SAFE_FREE(be); + NSS_DEBUG("_nss_winbind_passwd_destr"); + return NSS_STATUS_SUCCESS; +} + +static nss_backend_op_t passwd_ops[] = +{ + _nss_winbind_passwd_destr, + _nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */ + _nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */ + _nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */ + _nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */ + _nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */ +}; + +nss_backend_t* +_nss_winbind_passwd_constr (const char* db_name, + const char* src_name, + const char* cfg_args) +{ + nss_backend_t *be; + + if(!(be = SMB_MALLOC_P(nss_backend_t)) ) + return NULL; + + be->ops = passwd_ops; + be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t); + + NSS_DEBUG("Initialized nss_winbind passwd backend"); + return be; +} + +/***************************************************************** + GROUP database backend + *****************************************************************/ + +static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args) +{ + NSS_DEBUG("_nss_winbind_setgrent_solwrap"); + return _nss_winbind_setgrent(); +} + +static NSS_STATUS +_nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args) +{ + NSS_DEBUG("_nss_winbind_endgrent_solwrap"); + return _nss_winbind_endgrent(); +} + +static NSS_STATUS +_nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args) +{ + NSS_STATUS ret; + char* buffer = NSS_ARGS(args)->buf.buffer; + int buflen = NSS_ARGS(args)->buf.buflen; + struct group* result = (struct group*) NSS_ARGS(args)->buf.result; + int* errnop = &NSS_ARGS(args)->erange; + char logmsg[80]; + + ret = _nss_winbind_getgrent_r(result, buffer, + buflen, errnop); + + if(ret == NSS_STATUS_SUCCESS) + { + snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name); + NSS_DEBUG(logmsg); + NSS_ARGS(args)->returnval = (void*) result; + } else { + snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret); + NSS_DEBUG(logmsg); + } + + return ret; + +} + +static NSS_STATUS +_nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args) +{ + NSS_STATUS ret; + struct group* result = (struct group*) NSS_ARGS(args)->buf.result; + + NSS_DEBUG("_nss_winbind_getgrnam_solwrap"); + ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name, + result, + NSS_ARGS(args)->buf.buffer, + NSS_ARGS(args)->buf.buflen, + &NSS_ARGS(args)->erange); + + if(ret == NSS_STATUS_SUCCESS) + NSS_ARGS(args)->returnval = (void*) result; + + return ret; +} + +static NSS_STATUS +_nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args) +{ + NSS_STATUS ret; + struct group* result = (struct group*) NSS_ARGS(args)->buf.result; + + NSS_DEBUG("_nss_winbind_getgrgid_solwrap"); + ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid, + result, + NSS_ARGS(args)->buf.buffer, + NSS_ARGS(args)->buf.buflen, + &NSS_ARGS(args)->erange); + + if(ret == NSS_STATUS_SUCCESS) + NSS_ARGS(args)->returnval = (void*) result; + + return ret; +} + +static NSS_STATUS +_nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args) +{ + int errnop; + struct nss_groupsbymem *gmem = (struct nss_groupsbymem *)args; + + NSS_DEBUG("_nss_winbind_getgroupsbymember"); + + _nss_winbind_initgroups_dyn(gmem->username, + gmem->gid_array[0], /* Primary Group */ + &gmem->numgids, + &gmem->maxgids, + &gmem->gid_array, + gmem->maxgids, + &errnop); + + /* + * If the maximum number of gids have been found, return + * SUCCESS so the switch engine will stop searching. Otherwise + * return NOTFOUND so nsswitch will continue to get groups + * from the remaining database backends specified in the + * nsswitch.conf file. + */ + return (gmem->numgids == gmem->maxgids ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND); +} + +static NSS_STATUS +_nss_winbind_group_destr (nss_backend_t* be, void* args) +{ + SAFE_FREE(be); + NSS_DEBUG("_nss_winbind_group_destr"); + return NSS_STATUS_SUCCESS; +} + +static nss_backend_op_t group_ops[] = +{ + _nss_winbind_group_destr, + _nss_winbind_endgrent_solwrap, + _nss_winbind_setgrent_solwrap, + _nss_winbind_getgrent_solwrap, + _nss_winbind_getgrnam_solwrap, + _nss_winbind_getgrgid_solwrap, + _nss_winbind_getgroupsbymember_solwrap +}; + +nss_backend_t* +_nss_winbind_group_constr (const char* db_name, + const char* src_name, + const char* cfg_args) +{ + nss_backend_t* be; + + if(!(be = SMB_MALLOC_P(nss_backend_t)) ) + return NULL; + + be->ops = group_ops; + be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t); + + NSS_DEBUG("Initialized nss_winbind group backend"); + return be; +} + +/***************************************************************** + hosts and ipnodes backend + *****************************************************************/ +#if defined(SUNOS5) /* not compatible with HP-UX */ + +/* this parser is shared between get*byname and get*byaddr, as key type + in request is stored in different locations, I had to provide the + address family as an argument, caller must free the winbind response. */ + +static NSS_STATUS +parse_response(int af, nss_XbyY_args_t* argp, struct winbindd_response *response) +{ + struct hostent *he = (struct hostent *)argp->buf.result; + char *buffer = argp->buf.buffer; + int buflen = argp->buf.buflen; + NSS_STATUS ret; + + char *p, *data; + int addrcount = 0; + int len = 0; + struct in_addr *addrp; +#if defined(AF_INET6) + struct in6_addr *addrp6; +#endif + int i; + + /* response is tab separated list of ip addresses with hostname + and newline at the end. so at first we will strip newline + then construct list of addresses for hostent. + */ + p = strchr(response->data.winsresp, '\n'); + if(p) *p = '\0'; + else {/* it must be broken */ + argp->h_errno = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + for(; p != response->data.winsresp; p--) { + if(*p == '\t') addrcount++; + } + + if(addrcount == 0) {/* it must be broken */ + argp->h_errno = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + /* allocate space for addresses and h_addr_list */ + he->h_addrtype = af; + if( he->h_addrtype == AF_INET) { + he->h_length = sizeof(struct in_addr); + addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen, + sizeof(struct in_addr)); + addrp -= addrcount; + he->h_addr_list = (char **)ROUND_DOWN(addrp, sizeof (char*)); + he->h_addr_list -= addrcount+1; + } +#if defined(AF_INET6) + else { + he->h_length = sizeof(struct in6_addr); + addrp6 = (struct in6_addr *)ROUND_DOWN(buffer + buflen, + sizeof(struct in6_addr)); + addrp6 -= addrcount; + he->h_addr_list = (char **)ROUND_DOWN(addrp6, sizeof (char*)); + he->h_addr_list -= addrcount+1; + } +#endif + + /* buffer too small?! */ + if((char *)he->h_addr_list < buffer ) { + argp->erange = 1; + return NSS_STR_PARSE_ERANGE; + } + + data = response->data.winsresp; + for( i = 0; i < addrcount; i++) { + p = strchr(data, '\t'); + if(p == NULL) break; /* just in case... */ + + *p = '\0'; /* terminate the string */ + if(he->h_addrtype == AF_INET) { + he->h_addr_list[i] = (char *)&addrp[i]; + if ((addrp[i].s_addr = inet_addr(data)) == -1) { + argp->erange = 1; + return NSS_STR_PARSE_ERANGE; + } + } +#if defined(AF_INET6) + else { + he->h_addr_list[i] = (char *)&addrp6[i]; + if (strchr(data, ':') != 0) { + if (inet_pton(AF_INET6, data, &addrp6[i]) != 1) { + argp->erange = 1; + return NSS_STR_PARSE_ERANGE; + } + } else { + struct in_addr in4; + if ((in4.s_addr = inet_addr(data)) == -1) { + argp->erange = 1; + return NSS_STR_PARSE_ERANGE; + } + IN6_INADDR_TO_V4MAPPED(&in4, &addrp6[i]); + } + } +#endif + data = p+1; + } + + he->h_addr_list[i] = (char *)NULL; + + len = strlen(data); + if(len > he->h_addr_list - (char**)argp->buf.buffer) { + argp->erange = 1; + return NSS_STR_PARSE_ERANGE; + } + + /* this is a bit overkill to use _nss_netdb_aliases here since + there seems to be no aliases but it will create all data for us */ + he->h_aliases = _nss_netdb_aliases(data, len, buffer, + ((char*) he->h_addr_list) - buffer); + if(he->h_aliases == NULL) { + argp->erange = 1; + ret = NSS_STR_PARSE_ERANGE; + } else { + he->h_name = he->h_aliases[0]; + he->h_aliases++; + ret = NSS_STR_PARSE_SUCCESS; + } + + argp->returnval = (void*)he; + return ret; +} + +static NSS_STATUS +_nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args) +{ + nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args; + struct winbindd_response response; + struct winbindd_request request; + NSS_STATUS ret; + int af; + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + /* I assume there that AI_ADDRCONFIG cases are handled in nss + frontend code, at least it seems done so in solaris... + + we will give NO_DATA for pure IPv6; IPv4 will be returned for + AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map + IPv4 to IPv6. + */ +#if defined(AF_INET6) +#ifdef HAVE_NSS_XBYY_KEY_IPNODE + af = argp->key.ipnode.af_family; + if(af == AF_INET6 && argp->key.ipnode.flags == 0) { + argp->h_errno = NO_DATA; + return NSS_STATUS_UNAVAIL; + } +#else + /* I'm not that sure if this is correct, but... */ + af = AF_INET6; +#endif +#endif + + strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1); + request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0'; + + if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response)) + == NSS_STATUS_SUCCESS ) { + ret = parse_response(af, argp, &response); + } + + winbindd_free_response(&response); + return ret; +} + +static NSS_STATUS +_nss_winbind_hosts_getbyname(nss_backend_t* be, void *args) +{ + nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args; + struct winbindd_response response; + struct winbindd_request request; + NSS_STATUS ret; + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1); + request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0'; + + if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response)) + == NSS_STATUS_SUCCESS ) { + ret = parse_response(AF_INET, argp, &response); + } + + winbindd_free_response(&response); + return ret; +} + +static NSS_STATUS +_nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + nss_XbyY_args_t *argp = (nss_XbyY_args_t *)args; + const char *p; + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + +#if defined(AF_INET6) + /* winbindd currently does not resolve IPv6 */ + if(argp->key.hostaddr.type == AF_INET6) { + argp->h_errno = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr, + request.data.winsreq, sizeof request.data.winsreq); +#else + snprintf(request.data.winsreq, sizeof request.data.winsreq, + "%u.%u.%u.%u", + ((unsigned char *)argp->key.hostaddr.addr)[0], + ((unsigned char *)argp->key.hostaddr.addr)[1], + ((unsigned char *)argp->key.hostaddr.addr)[2], + ((unsigned char *)argp->key.hostaddr.addr)[3]); +#endif + + ret = winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response); + + if( ret == NSS_STATUS_SUCCESS) { + parse_response(argp->key.hostaddr.type, argp, &response); + } + winbindd_free_response(&response); + return ret; +} + +/* winbind does not provide setent, getent, endent for wins */ +static NSS_STATUS +_nss_winbind_common_endent(nss_backend_t* be, void *args) +{ + return (NSS_STATUS_UNAVAIL); +} + +static NSS_STATUS +_nss_winbind_common_setent(nss_backend_t* be, void *args) +{ + return (NSS_STATUS_UNAVAIL); +} + +static NSS_STATUS +_nss_winbind_common_getent(nss_backend_t* be, void *args) +{ + return (NSS_STATUS_UNAVAIL); +} + +static nss_backend_t* +_nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops) +{ + nss_backend_t* be; + + if(!(be = SMB_MALLOC_P(nss_backend_t)) ) + return NULL; + + be->ops = ops; + be->n_ops = n_ops; + + return be; +} + +static NSS_STATUS +_nss_winbind_common_destr (nss_backend_t* be, void* args) +{ + SAFE_FREE(be); + return NSS_STATUS_SUCCESS; +} + +static nss_backend_op_t ipnodes_ops[] = { + _nss_winbind_common_destr, + _nss_winbind_common_endent, + _nss_winbind_common_setent, + _nss_winbind_common_getent, + _nss_winbind_ipnodes_getbyname, + _nss_winbind_hosts_getbyaddr, +}; + +nss_backend_t * +_nss_winbind_ipnodes_constr(dummy1, dummy2, dummy3) + const char *dummy1, *dummy2, *dummy3; +{ + return (_nss_winbind_common_constr(ipnodes_ops, + sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0]))); +} + +static nss_backend_op_t host_ops[] = { + _nss_winbind_common_destr, + _nss_winbind_common_endent, + _nss_winbind_common_setent, + _nss_winbind_common_getent, + _nss_winbind_hosts_getbyname, + _nss_winbind_hosts_getbyaddr, +}; + +nss_backend_t * +_nss_winbind_hosts_constr(dummy1, dummy2, dummy3) + const char *dummy1, *dummy2, *dummy3; +{ + return (_nss_winbind_common_constr(host_ops, + sizeof (host_ops) / sizeof (host_ops[0]))); +} + +#endif /* defined(SUNOS5) */ +#endif /* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */ diff --git a/nsswitch/winbind_nss_solaris.h b/nsswitch/winbind_nss_solaris.h new file mode 100644 index 0000000000..c6cadefc38 --- /dev/null +++ b/nsswitch/winbind_nss_solaris.h @@ -0,0 +1,85 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef _WINBIND_NSS_SOLARIS_H +#define _WINBIND_NSS_SOLARIS_H + +/* Solaris has a broken nss_common header file containing C++ reserved names. */ +#ifndef __cplusplus +#undef class +#undef private +#undef public +#undef protected +#undef template +#undef this +#undef new +#undef delete +#undef friend +#endif + +#include + +#ifndef __cplusplus +#define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define this #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define new #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define delete #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#define friend #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +#endif + +#include +#include + +typedef nss_status_t NSS_STATUS; + +#define NSS_STATUS_SUCCESS NSS_SUCCESS +#define NSS_STATUS_NOTFOUND NSS_NOTFOUND +#define NSS_STATUS_UNAVAIL NSS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN + +/* The solaris winbind is implemented as a wrapper around the linux + version. */ + +NSS_STATUS _nss_winbind_setpwent(void); +NSS_STATUS _nss_winbind_endpwent(void); +NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer, + size_t buflen, int* errnop); +NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer, + size_t buflen, int* errnop); +NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result, + char* buffer, size_t buflen, int* errnop); + +NSS_STATUS _nss_winbind_setgrent(void); +NSS_STATUS _nss_winbind_endgrent(void); +NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer, + size_t buflen, int* errnop); +NSS_STATUS _nss_winbind_getgrnam_r(const char *name, + struct group *result, char *buffer, + size_t buflen, int *errnop); +NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, + struct group *result, char *buffer, + size_t buflen, int *errnop); + +#endif /* _WINBIND_NSS_SOLARIS_H */ diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h new file mode 100644 index 0000000000..fe3da81791 --- /dev/null +++ b/nsswitch/winbind_struct_protocol.h @@ -0,0 +1,514 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon for ntdom nss module + + Copyright (C) Tim Potter 2000 + Copyright (C) Gerald Carter 2006 + + You are free to use this interface definition in any way you see + fit, including without restriction, using this header in your own + products. You do not need to give any attribution. +*/ + +#ifndef SAFE_FREE +#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0) +#endif + +#ifndef _WINBINDD_NTDOM_H +#define _WINBINDD_NTDOM_H + +#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */ + +/* Let the build environment override the public winbindd socket location. This + * is needed for launchd support -- jpeach. + */ +#ifndef WINBINDD_SOCKET_DIR +#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */ +#endif + +/* + * when compiled with socket_wrapper support + * the location of the WINBINDD_SOCKET_DIR + * can be overwritten via an environment variable + */ +#define WINBINDD_SOCKET_DIR_ENVVAR "WINBINDD_SOCKET_DIR" + +#define WINBINDD_PRIV_SOCKET_SUBDIR "winbindd_privileged" /* name of subdirectory of lp_lockdir() to hold the 'privileged' pipe */ +#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */ +#define WINBINDD_DONT_ENV "_NO_WINBINDD" +#define WINBINDD_LOCATOR_KDC_ADDRESS "WINBINDD_LOCATOR_KDC_ADDRESS" + +/* Update this when you change the interface. */ + +#define WINBIND_INTERFACE_VERSION 20 + +/* Have to deal with time_t being 4 or 8 bytes due to structure alignment. + On a 64bit Linux box, we have to support a constant structure size + between /lib/libnss_winbind.so.2 and /li64/libnss_winbind.so.2. + The easiest way to do this is to always use 8byte values for time_t. */ + +#define SMB_TIME_T int64_t + +/* Socket commands */ + +enum winbindd_cmd { + + WINBINDD_INTERFACE_VERSION, /* Always a well known value */ + + /* Get users and groups */ + + WINBINDD_GETPWNAM, + WINBINDD_GETPWUID, + WINBINDD_GETGRNAM, + WINBINDD_GETGRGID, + WINBINDD_GETGROUPS, + + /* Enumerate users and groups */ + + WINBINDD_SETPWENT, + WINBINDD_ENDPWENT, + WINBINDD_GETPWENT, + WINBINDD_SETGRENT, + WINBINDD_ENDGRENT, + WINBINDD_GETGRENT, + + /* PAM authenticate and password change */ + + WINBINDD_PAM_AUTH, + WINBINDD_PAM_AUTH_CRAP, + WINBINDD_PAM_CHAUTHTOK, + WINBINDD_PAM_LOGOFF, + WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, + + /* List various things */ + + WINBINDD_LIST_USERS, /* List w/o rid->id mapping */ + WINBINDD_LIST_GROUPS, /* Ditto */ + WINBINDD_LIST_TRUSTDOM, + + /* SID conversion */ + + WINBINDD_LOOKUPSID, + WINBINDD_LOOKUPNAME, + WINBINDD_LOOKUPRIDS, + + /* Lookup functions */ + + WINBINDD_SID_TO_UID, + WINBINDD_SID_TO_GID, + WINBINDD_SIDS_TO_XIDS, + WINBINDD_UID_TO_SID, + WINBINDD_GID_TO_SID, + + WINBINDD_ALLOCATE_UID, + WINBINDD_ALLOCATE_GID, + WINBINDD_SET_MAPPING, + WINBINDD_REMOVE_MAPPING, + WINBINDD_SET_HWM, + + /* Miscellaneous other stuff */ + + WINBINDD_CHECK_MACHACC, /* Check machine account pw works */ + WINBINDD_PING, /* Just tell me winbind is running */ + WINBINDD_INFO, /* Various bit of info. Currently just tidbits */ + WINBINDD_DOMAIN_NAME, /* The domain this winbind server is a member of (lp_workgroup()) */ + + WINBINDD_DOMAIN_INFO, /* Most of what we know from + struct winbindd_domain */ + WINBINDD_GETDCNAME, /* Issue a GetDCName Request */ + WINBINDD_DSGETDCNAME, /* Issue a DsGetDCName Request */ + + WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */ + + /* WINS commands */ + + WINBINDD_WINS_BYIP, + WINBINDD_WINS_BYNAME, + + /* this is like GETGRENT but gives an empty group list */ + WINBINDD_GETGRLST, + + WINBINDD_NETBIOS_NAME, /* The netbios name of the server */ + + /* find the location of our privileged pipe */ + WINBINDD_PRIV_PIPE_DIR, + + /* return a list of group sids for a user sid */ + WINBINDD_GETUSERSIDS, + + /* Various group queries */ + WINBINDD_GETUSERDOMGROUPS, + + /* Initialize connection in a child */ + WINBINDD_INIT_CONNECTION, + + /* Blocking calls that are not allowed on the main winbind pipe, only + * between parent and children */ + WINBINDD_DUAL_SID2UID, + WINBINDD_DUAL_SID2GID, + WINBINDD_DUAL_SIDS2XIDS, + WINBINDD_DUAL_UID2SID, + WINBINDD_DUAL_GID2SID, + WINBINDD_DUAL_SET_MAPPING, + WINBINDD_DUAL_REMOVE_MAPPING, + WINBINDD_DUAL_SET_HWM, + + /* Wrapper around possibly blocking unix nss calls */ + WINBINDD_DUAL_USERINFO, + WINBINDD_DUAL_GETSIDALIASES, + + /* Complete the challenge phase of the NTLM authentication + protocol using cached password. */ + WINBINDD_CCACHE_NTLMAUTH, + + WINBINDD_NUM_CMDS +}; + +typedef struct winbindd_pw { + fstring pw_name; + fstring pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + fstring pw_gecos; + fstring pw_dir; + fstring pw_shell; +} WINBINDD_PW; + + +typedef struct winbindd_gr { + fstring gr_name; + fstring gr_passwd; + gid_t gr_gid; + uint32_t num_gr_mem; + uint32_t gr_mem_ofs; /* offset to group membership */ +} WINBINDD_GR; + +/* PAM specific request flags */ +#define WBFLAG_PAM_INFO3_NDR 0x00000001 +#define WBFLAG_PAM_INFO3_TEXT 0x00000002 +#define WBFLAG_PAM_USER_SESSION_KEY 0x00000004 +#define WBFLAG_PAM_LMKEY 0x00000008 +#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x00000010 +#define WBFLAG_PAM_UNIX_NAME 0x00000080 +#define WBFLAG_PAM_AFS_TOKEN 0x00000100 +#define WBFLAG_PAM_NT_STATUS_SQUASH 0x00000200 +#define WBFLAG_PAM_KRB5 0x00001000 +#define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x00002000 +#define WBFLAG_PAM_CACHED_LOGIN 0x00004000 +#define WBFLAG_PAM_GET_PWD_POLICY 0x00008000 + +/* generic request flags */ +#define WBFLAG_QUERY_ONLY 0x00000020 /* not used */ +/* This is a flag that can only be sent from parent to child */ +#define WBFLAG_IS_PRIVILEGED 0x00000400 /* not used */ +/* Flag to say this is a winbindd internal send - don't recurse. */ +#define WBFLAG_RECURSE 0x00000800 +/* Flag to tell winbind the NTLMv2 blob is too big for the struct and is in the + * extra_data field */ +#define WBFLAG_BIG_NTLMV2_BLOB 0x00010000 + +#define WINBINDD_MAX_EXTRA_DATA (128*1024) + +/* Winbind request structure */ + +/******************************************************************************* + * This structure MUST be the same size in the 32bit and 64bit builds + * for compatibility between /lib64/libnss_winbind.so and /lib/libnss_winbind.so + * + * DO NOT CHANGE THIS STRUCTURE WITHOUT TESTING THE 32BIT NSS LIB AGAINST + * A 64BIT WINBINDD --jerry + ******************************************************************************/ + +struct winbindd_request { + uint32_t length; + enum winbindd_cmd cmd; /* Winbindd command to execute */ + enum winbindd_cmd original_cmd; /* Original Winbindd command + issued to parent process */ + pid_t pid; /* pid of calling process */ + uint32_t wb_flags; /* generic flags */ + uint32_t flags; /* flags relevant *only* to a given request */ + fstring domain_name; /* name of domain for which the request applies */ + + union { + fstring winsreq; /* WINS request */ + fstring username; /* getpwnam */ + fstring groupname; /* getgrnam */ + uid_t uid; /* getpwuid, uid_to_sid */ + gid_t gid; /* getgrgid, gid_to_sid */ + struct { + /* We deliberatedly don't split into domain/user to + avoid having the client know what the separator + character is. */ + fstring user; + fstring pass; + char require_membership_of_sid[1024]; + fstring krb5_cc_type; + uid_t uid; + } auth; /* pam_winbind auth module */ + struct { + uint8_t chal[8]; + uint32_t logon_parameters; + fstring user; + fstring domain; + fstring lm_resp; + uint32_t lm_resp_len; + fstring nt_resp; + uint32_t nt_resp_len; + fstring workstation; + fstring require_membership_of_sid; + } auth_crap; + struct { + fstring user; + fstring oldpass; + fstring newpass; + } chauthtok; /* pam_winbind passwd module */ + struct { + fstring user; + fstring domain; + uint8_t new_nt_pswd[516]; + uint16_t new_nt_pswd_len; + uint8_t old_nt_hash_enc[16]; + uint16_t old_nt_hash_enc_len; + uint8_t new_lm_pswd[516]; + uint16_t new_lm_pswd_len; + uint8_t old_lm_hash_enc[16]; + uint16_t old_lm_hash_enc_len; + } chng_pswd_auth_crap;/* pam_winbind passwd module */ + struct { + fstring user; + fstring krb5ccname; + uid_t uid; + } logoff; /* pam_winbind session module */ + fstring sid; /* lookupsid, sid_to_[ug]id */ + struct { + fstring dom_name; /* lookupname */ + fstring name; + } name; + uint32_t num_entries; /* getpwent, getgrent */ + struct { + fstring username; + fstring groupname; + } acct_mgt; + struct { + bool is_primary; + fstring dcname; + } init_conn; + struct { + fstring sid; + fstring name; + } dual_sid2id; + struct { + fstring sid; + uint32_t type; + uint32_t id; + } dual_idmapset; + bool list_all_domains; + + struct { + uid_t uid; + fstring user; + /* the effective uid of the client, must be the uid for 'user'. + This is checked by the main daemon, trusted by children. */ + /* if the blobs are length zero, then this doesn't + produce an actual challenge response. It merely + succeeds if there are cached credentials available + that could be used. */ + uint32_t initial_blob_len; /* blobs in extra_data */ + uint32_t challenge_blob_len; + } ccache_ntlm_auth; + struct { + fstring domain_name; + fstring domain_guid; + fstring site_name; + uint32_t flags; + } dsgetdcname; + + /* padding -- needed to fix alignment between 32bit and 64bit libs. + The size is the sizeof the union without the padding aligned on + an 8 byte boundary. --jerry */ + + char padding[1800]; + } data; + union { + SMB_TIME_T padding; + char *data; + } extra_data; + uint32_t extra_len; + char null_term; +}; + +/* Response values */ + +enum winbindd_result { + WINBINDD_ERROR, + WINBINDD_PENDING, + WINBINDD_OK +}; + +/* Winbind response structure */ + +/******************************************************************************* + * This structure MUST be the same size in the 32bit and 64bit builds + * for compatibility between /lib64/libnss_winbind.so and /lib/libnss_winbind.so + * + * DO NOT CHANGE THIS STRUCTURE WITHOUT TESTING THE 32BIT NSS LIB AGAINST + * A 64BIT WINBINDD --jerry + ******************************************************************************/ + +struct winbindd_response { + + /* Header information */ + + uint32_t length; /* Length of response */ + enum winbindd_result result; /* Result code */ + + /* Fixed length return data */ + + union { + int interface_version; /* Try to ensure this is always in the same spot... */ + + fstring winsresp; /* WINS response */ + + /* getpwnam, getpwuid */ + + struct winbindd_pw pw; + + /* getgrnam, getgrgid */ + + struct winbindd_gr gr; + + uint32_t num_entries; /* getpwent, getgrent */ + struct winbindd_sid { + fstring sid; /* lookupname, [ug]id_to_sid */ + int type; + } sid; + struct winbindd_name { + fstring dom_name; /* lookupsid */ + fstring name; + int type; + } name; + uid_t uid; /* sid_to_uid */ + gid_t gid; /* sid_to_gid */ + struct winbindd_info { + char winbind_separator; + fstring samba_version; + } info; + fstring domain_name; + fstring netbios_name; + fstring dc_name; + + struct auth_reply { + uint32_t nt_status; + fstring nt_status_string; + fstring error_string; + int pam_error; + char user_session_key[16]; + char first_8_lm_hash[8]; + fstring krb5ccname; + uint32_t reject_reason; + uint32_t padding; + struct policy_settings { + uint32_t min_length_password; + uint32_t password_history; + uint32_t password_properties; + uint32_t padding; + SMB_TIME_T expire; + SMB_TIME_T min_passwordage; + } policy; + struct info3_text { + SMB_TIME_T logon_time; + SMB_TIME_T logoff_time; + SMB_TIME_T kickoff_time; + SMB_TIME_T pass_last_set_time; + SMB_TIME_T pass_can_change_time; + SMB_TIME_T pass_must_change_time; + uint32_t logon_count; + uint32_t bad_pw_count; + uint32_t user_rid; + uint32_t group_rid; + uint32_t num_groups; + uint32_t user_flgs; + uint32_t acct_flags; + uint32_t num_other_sids; + fstring dom_sid; + fstring user_name; + fstring full_name; + fstring logon_script; + fstring profile_path; + fstring home_dir; + fstring dir_drive; + fstring logon_srv; + fstring logon_dom; + } info3; + fstring unix_username; + } auth; + struct { + fstring name; + fstring alt_name; + fstring sid; + bool native_mode; + bool active_directory; + bool primary; + } domain_info; + uint32_t sequence_number; + struct { + fstring acct_name; + fstring full_name; + fstring homedir; + fstring shell; + uint32_t primary_gid; + uint32_t group_rid; + } user_info; + struct { + uint32_t auth_blob_len; /* blob in extra_data */ + } ccache_ntlm_auth; + struct { + fstring dc_unc; + fstring dc_address; + uint32_t dc_address_type; + fstring domain_guid; + fstring domain_name; + fstring forest_name; + uint32_t dc_flags; + fstring dc_site_name; + fstring client_site_name; + } dsgetdcname; + } data; + + /* Variable length return data */ + + union { + SMB_TIME_T padding; + void *data; + } extra_data; +}; + +struct WINBINDD_MEMORY_CREDS { + struct WINBINDD_MEMORY_CREDS *next, *prev; + const char *username; /* lookup key. */ + uid_t uid; + int ref_count; + size_t len; + uint8_t *nt_hash; /* Base pointer for the following 2 */ + uint8_t *lm_hash; + char *pass; +}; + +struct WINBINDD_CCACHE_ENTRY { + struct WINBINDD_CCACHE_ENTRY *next, *prev; + const char *principal_name; + const char *ccname; + const char *service; + const char *username; + const char *realm; + struct WINBINDD_MEMORY_CREDS *cred_ptr; + int ref_count; + uid_t uid; + time_t create_time; + time_t renew_until; + time_t refresh_time; + struct timed_event *event; +}; + +#endif diff --git a/nsswitch/wins.c b/nsswitch/wins.c new file mode 100644 index 0000000000..80f0119108 --- /dev/null +++ b/nsswitch/wins.c @@ -0,0 +1,446 @@ +/* + Unix SMB/CIFS implementation. + a WINS nsswitch module + 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 3 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, see . + +*/ + +#include "includes.h" +#ifdef HAVE_NS_API_H + +#include +#endif + +#if HAVE_PTHREAD_H +#include +#endif + +#if HAVE_PTHREAD +static pthread_mutex_t wins_nss_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +#ifndef INADDRSZ +#define INADDRSZ 4 +#endif + +static int initialised; + +extern bool AllowDebugChange; + +NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop); +NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop); + +/* Use our own create socket code so we don't recurse.... */ + +static int wins_lookup_open_socket_in(void) +{ + struct sockaddr_in sock; + int val=1; + int res; + + memset((char *)&sock,'\0',sizeof(sock)); + +#ifdef HAVE_SOCK_SIN_LEN + sock.sin_len = sizeof(sock); +#endif + sock.sin_port = 0; + sock.sin_family = AF_INET; + sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); + res = socket(AF_INET, SOCK_DGRAM, 0); + if (res == -1) + return -1; + + if (setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)) != 0) { + close(res); + return -1; + } +#ifdef SO_REUSEPORT + if (setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)) != 0) { + close(res); + return -1; + } +#endif /* SO_REUSEPORT */ + + /* now we've got a socket - we need to bind it */ + + if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { + close(res); + return(-1); + } + + set_socket_options(res,"SO_BROADCAST"); + + return res; +} + + +static void nss_wins_init(void) +{ + initialised = 1; + DEBUGLEVEL = 0; + AllowDebugChange = False; + + TimeInit(); + setup_logging("nss_wins",False); + load_case_tables(); + lp_load(get_dyn_CONFIGFILE(),True,False,False,True); + load_interfaces(); +} + +static struct in_addr *lookup_byname_backend(const char *name, int *count) +{ + int fd = -1; + struct ip_service *address = NULL; + struct in_addr *ret = NULL; + int j, flags = 0; + + if (!initialised) { + nss_wins_init(); + } + + *count = 0; + + /* always try with wins first */ + if (NT_STATUS_IS_OK(resolve_wins(name,0x00,&address,count))) { + if ( (ret = SMB_MALLOC_P(struct in_addr)) == NULL ) { + free( address ); + return NULL; + } + if (address[0].ss.ss_family != AF_INET) { + free(address); + free(ret); + return NULL; + } + *ret = ((struct sockaddr_in *)&address[0].ss)->sin_addr; + free( address ); + return ret; + } + + fd = wins_lookup_open_socket_in(); + if (fd == -1) { + return NULL; + } + + /* uggh, we have to broadcast to each interface in turn */ + for (j=iface_count() - 1;j >= 0;j--) { + const struct in_addr *bcast = iface_n_bcast_v4(j); + struct sockaddr_storage ss; + struct sockaddr_storage *pss; + if (!bcast) { + continue; + } + in_addr_to_sockaddr_storage(&ss, *bcast); + pss = name_query(fd,name,0x00,True,True,&ss,count, &flags, NULL); + if (pss) { + if ((ret = SMB_MALLOC_P(struct in_addr)) == NULL) { + return NULL; + } + *ret = ((struct sockaddr_in *)pss)->sin_addr; + break; + } + } + + close(fd); + return ret; +} + +#ifdef HAVE_NS_API_H + +static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count) +{ + int fd; + struct sockaddr_storage ss; + struct nmb_name nname; + NODE_STATUS_STRUCT *status; + + if (!initialised) { + nss_wins_init(); + } + + fd = wins_lookup_open_socket_in(); + if (fd == -1) + return NULL; + + make_nmb_name(&nname, "*", 0); + if (!interpret_string_addr(&ss, addr, AI_NUMERICHOST)) { + return NULL; + } + status = node_status_query(fd, &nname, &ss, count, NULL); + + close(fd); + return status; +} + +/* IRIX version */ + +int init(void) +{ + nsd_logprintf(NSD_LOG_MIN, "entering init (wins)\n"); + nss_wins_init(); + return NSD_OK; +} + +int lookup(nsd_file_t *rq) +{ + char *map; + char *key; + char *addr; + struct in_addr *ip_list; + NODE_STATUS_STRUCT *status; + int i, count, len, size; + char response[1024]; + bool found = False; + + nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n"); + if (! rq) + return NSD_ERROR; + + map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); + if (! map) { + rq->f_status = NS_FATAL; + return NSD_ERROR; + } + + key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); + if (! key || ! *key) { + rq->f_status = NS_FATAL; + return NSD_ERROR; + } + + response[0] = '\0'; + len = sizeof(response) - 2; + + /* + * response needs to be a string of the following format + * ip_address[ ip_address]*\tname[ alias]* + */ + if (StrCaseCmp(map,"hosts.byaddr") == 0) { + if ( status = lookup_byaddr_backend(key, &count)) { + size = strlen(key) + 1; + if (size > len) { + free(status); + return NSD_ERROR; + } + len -= size; + strncat(response,key,size); + strncat(response,"\t",1); + for (i = 0; i < count; i++) { + /* ignore group names */ + if (status[i].flags & 0x80) continue; + if (status[i].type == 0x20) { + size = sizeof(status[i].name) + 1; + if (size > len) { + free(status); + return NSD_ERROR; + } + len -= size; + strncat(response, status[i].name, size); + strncat(response, " ", 1); + found = True; + } + } + response[strlen(response)-1] = '\n'; + free(status); + } + } else if (StrCaseCmp(map,"hosts.byname") == 0) { + if (ip_list = lookup_byname_backend(key, &count)) { + for (i = count; i ; i--) { + addr = inet_ntoa(ip_list[i-1]); + size = strlen(addr) + 1; + if (size > len) { + free(ip_list); + return NSD_ERROR; + } + len -= size; + if (i != 0) + response[strlen(response)-1] = ' '; + strncat(response,addr,size); + strncat(response,"\t",1); + } + size = strlen(key) + 1; + if (size > len) { + free(ip_list); + return NSD_ERROR; + } + strncat(response,key,size); + strncat(response,"\n",1); + found = True; + free(ip_list); + } + } + + if (found) { + nsd_logprintf(NSD_LOG_LOW, "lookup (wins %s) %s\n",map,response); + nsd_set_result(rq,NS_SUCCESS,response,strlen(response),VOLATILE); + return NSD_OK; + } + nsd_logprintf(NSD_LOG_LOW, "lookup (wins) not found\n"); + rq->f_status = NS_NOTFOUND; + return NSD_NEXT; +} + +#else + +/* Allocate some space from the nss static buffer. The buffer and buflen + are the pointers passed in by the C library to the _nss_*_* + functions. */ + +static char *get_static(char **buffer, size_t *buflen, int len) +{ + char *result; + + /* Error check. We return false if things aren't set up right, or + there isn't enough buffer space left. */ + + if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { + return NULL; + } + + /* Return an index into the static buffer */ + + result = *buffer; + *buffer += len; + *buflen -= len; + + return result; +} + +/**************************************************************************** +gethostbyname() - we ignore any domain portion of the name and only +handle names that are at most 15 characters long + **************************************************************************/ +NSS_STATUS +_nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop) +{ + NSS_STATUS nss_status = NSS_STATUS_SUCCESS; + struct in_addr *ip_list; + int i, count; + fstring name; + size_t namelen; + +#if HAVE_PTHREAD + pthread_mutex_lock(&wins_nss_mutex); +#endif + + memset(he, '\0', sizeof(*he)); + fstrcpy(name, hostname); + + /* Do lookup */ + + ip_list = lookup_byname_backend(name, &count); + + if (!ip_list) { + nss_status = NSS_STATUS_NOTFOUND; + goto out; + } + + /* Copy h_name */ + + namelen = strlen(name) + 1; + + if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL) { + free(ip_list); + nss_status = NSS_STATUS_TRYAGAIN; + goto out; + } + + memcpy(he->h_name, name, namelen); + + /* Copy h_addr_list, align to pointer boundary first */ + + if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0) + i = sizeof(char*) - i; + + if (get_static(&buffer, &buflen, i) == NULL) { + free(ip_list); + nss_status = NSS_STATUS_TRYAGAIN; + goto out; + } + + if ((he->h_addr_list = (char **)get_static( + &buffer, &buflen, (count + 1) * sizeof(char *))) == NULL) { + free(ip_list); + nss_status = NSS_STATUS_TRYAGAIN; + goto out; + } + + for (i = 0; i < count; i++) { + if ((he->h_addr_list[i] = get_static(&buffer, &buflen, + INADDRSZ)) == NULL) { + free(ip_list); + nss_status = NSS_STATUS_TRYAGAIN; + goto out; + } + memcpy(he->h_addr_list[i], &ip_list[i], INADDRSZ); + } + + he->h_addr_list[count] = NULL; + + free(ip_list); + + /* Set h_addr_type and h_length */ + + he->h_addrtype = AF_INET; + he->h_length = INADDRSZ; + + /* Set h_aliases */ + + if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0) + i = sizeof(char*) - i; + + if (get_static(&buffer, &buflen, i) == NULL) { + nss_status = NSS_STATUS_TRYAGAIN; + goto out; + } + + if ((he->h_aliases = (char **)get_static( + &buffer, &buflen, sizeof(char *))) == NULL) { + nss_status = NSS_STATUS_TRYAGAIN; + goto out; + } + + he->h_aliases[0] = NULL; + + nss_status = NSS_STATUS_SUCCESS; + + out: + +#if HAVE_PTHREAD + pthread_mutex_unlock(&wins_nss_mutex); +#endif + return nss_status; +} + + +NSS_STATUS +_nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop) +{ + NSS_STATUS nss_status; + + if(af!=AF_INET) { + *h_errnop = NO_DATA; + nss_status = NSS_STATUS_UNAVAIL; + } else { + nss_status = _nss_wins_gethostbyname_r( + name, he, buffer, buflen, h_errnop); + } + return nss_status; +} +#endif diff --git a/source3/Makefile.in b/source3/Makefile.in index f53406c39e..e30da1b7a0 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -244,7 +244,7 @@ SMBLDAP_OBJ = @SMBLDAP@ @SMBLDAPUTIL@ VERSION_OBJ = lib/version.o -WBCOMMON_OBJ = nsswitch/wb_common.o +WBCOMMON_OBJ = ../nsswitch/wb_common.o AFS_OBJ = lib/afs.o @@ -809,7 +809,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(LIBADS_OBJ) $(POPT_LIB_OBJ) \ $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(LDB_OBJ) -PAM_WINBIND_OBJ = nsswitch/pam_winbind.o localedir.o $(WBCOMMON_OBJ) \ +PAM_WINBIND_OBJ = ../nsswitch/pam_winbind.o localedir.o $(WBCOMMON_OBJ) \ $(LIBREPLACE_OBJ) @BUILD_INIPARSER@ LIBSMBCLIENT_OBJ0 = \ @@ -1009,7 +1009,7 @@ SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \ $(LIBNDR_GEN_OBJ0) -WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \ +WINBIND_WINS_NSS_OBJ = ../nsswitch/wins.o $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) \ $(LIBNDR_GEN_OBJ0) @@ -1073,7 +1073,7 @@ WINBINDD_OBJ = \ $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \ $(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ) $(LDB_OBJ) -WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ +WBINFO_OBJ = ../nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ) \ lib/winbind_util.o $(WBCOMMON_OBJ) @LIBWBCLIENT_STATIC@ @@ -1110,7 +1110,7 @@ LDBADD_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbadd.o LDBDEL_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbdel.o LDBMODIFY_OBJ = $(LDB_CMDLINE_OBJ) lib/ldb/tools/ldbmodify.o -WINBIND_KRB5_LOCATOR_OBJ1 = nsswitch/winbind_krb5_locator.o +WINBIND_KRB5_LOCATOR_OBJ1 = ../nsswitch/winbind_krb5_locator.o WINBIND_KRB5_LOCATOR_OBJ = $(WINBIND_KRB5_LOCATOR_OBJ1) $(LIBREPLACE_OBJ) POPT_OBJ=../lib/popt/findme.o ../lib/popt/popt.o ../lib/popt/poptconfig.o \ @@ -1767,13 +1767,13 @@ shlibs test_shlibs: @LIBTDB_SHARED@ # #------------------------------------------------------------------- -LIBWBCLIENT_OBJ0 = nsswitch/libwbclient/wbclient.o \ - nsswitch/libwbclient/wbc_util.o \ - nsswitch/libwbclient/wbc_pwd.o \ - nsswitch/libwbclient/wbc_idmap.o \ - nsswitch/libwbclient/wbc_sid.o \ - nsswitch/libwbclient/wbc_guid.o \ - nsswitch/libwbclient/wbc_pam.o +LIBWBCLIENT_OBJ0 = ../nsswitch/libwbclient/wbclient.o \ + ../nsswitch/libwbclient/wbc_util.o \ + ../nsswitch/libwbclient/wbc_pwd.o \ + ../nsswitch/libwbclient/wbc_idmap.o \ + ../nsswitch/libwbclient/wbc_sid.o \ + ../nsswitch/libwbclient/wbc_guid.o \ + ../nsswitch/libwbclient/wbc_pam.o LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) \ $(WBCOMMON_OBJ) \ @LIBTALLOC_STATIC@ $(LIBREPLACE_OBJ) @@ -1784,7 +1784,7 @@ LIBWBCLIENT_SHARED_TARGET_SONAME=$(LIBWBCLIENT_SHARED_TARGET).$(LIBWBCLIENT_SOVE LIBWBCLIENT_STATIC_TARGET=@LIBWBCLIENT_STATIC_TARGET@ LIBWBCLIENT=@LIBWBCLIENT_STATIC@ @LIBWBCLIENT_SHARED@ LIBWBCLIENT_SYMS=$(srcdir)/exports/libwbclient.@SYMSEXT@ -LIBWBCLIENT_HEADERS=$(srcdir)/nsswitch/libwbclient/wbclient.h +LIBWBCLIENT_HEADERS=$(srcdir)/../nsswitch/libwbclient/wbclient.h $(LIBWBCLIENT_SYMS): $(LIBWBCLIENT_HEADERS) @$(MKSYMS_SH) $(AWK) $@ $(LIBWBCLIENT_HEADERS) @@ -2776,7 +2776,7 @@ etags:: etags --append `find $(srcdir)/../source4/ldap_server -name "*.[ch]"` etags --append `find $(srcdir)/../source4/smb_server -name "*.[ch]"` etags --append `find $(srcdir)/../source4/include -name "*.[ch]"` - etags --append `find $(srcdir)/../source4/nsswitch -name "*.[ch]"` + etags --append `find $(srcdir)/../nsswitch -name "*.[ch]"` etags --append `find $(srcdir)/../source4/cldap_server -name "*.[ch]"` etags --append `find $(srcdir)/../source4/utils -name "*.[ch]"` etags --append `find $(srcdir)/../source4/librpc -name "*.[ch]"` diff --git a/source3/configure.in b/source3/configure.in index b90b1b3f60..42bdddf5f9 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -5699,8 +5699,8 @@ HAVE_WINBIND=yes # Define the winbind shared library name and any specific linker flags # it needs to be built with. -WINBIND_NSS="nsswitch/libnss_winbind.$SHLIBEXT" -WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT" +WINBIND_NSS="../nsswitch/libnss_winbind.$SHLIBEXT" +WINBIND_WINS_NSS="../nsswitch/libnss_wins.$SHLIBEXT" WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS NSSSONAMEVERSIONSUFFIX="" WINBIND_NSS_PTHREAD="" @@ -5708,16 +5708,16 @@ WINBIND_NSS_PTHREAD="" case "$host_os" in *linux*) NSSSONAMEVERSIONSUFFIX=".2" - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_linux.o" + WINBIND_NSS_EXTRA_OBJS="../nsswitch/winbind_nss_linux.o" ;; *freebsd[[5-9]]*) # FreeBSD winbind client is implemented as a wrapper around # the Linux version. NSSSONAMEVERSIONSUFFIX=".1" - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_freebsd.o \ - nsswitch/winbind_nss_linux.o" - WINBIND_NSS="nsswitch/nss_winbind.$SHLIBEXT" - WINBIND_WINS_NSS="nsswitch/nss_wins.$SHLIBEXT" + WINBIND_NSS_EXTRA_OBJS="../nsswitch/winbind_nss_freebsd.o \ + ../nsswitch/winbind_nss_linux.o" + WINBIND_NSS="../nsswitch/nss_winbind.$SHLIBEXT" + WINBIND_WINS_NSS="../nsswitch/nss_wins.$SHLIBEXT" ;; *netbsd*[[3-9]]*) @@ -5727,10 +5727,10 @@ case "$host_os" in # if test x"$ac_cv_func_getpwent_r" = x"yes"; then WINBIND_NSS_EXTRA_OBJS="\ - nsswitch/winbind_nss_netbsd.o \ - nsswitch/winbind_nss_linux.o" - WINBIND_NSS="nsswitch/nss_winbind.$SHLIBEXT" - WINBIND_WINS_NSS="nsswitch/nss_wins.$SHLIBEXT" + ../nsswitch/winbind_nss_netbsd.o \ + ../nsswitch/winbind_nss_linux.o" + WINBIND_NSS="../nsswitch/nss_winbind.$SHLIBEXT" + WINBIND_WINS_NSS="../nsswitch/nss_wins.$SHLIBEXT" else HAVE_WINBIND=no winbind_no_reason=", getpwent_r is missing on $host_os so winbind is unsupported" @@ -5738,28 +5738,28 @@ case "$host_os" in ;; *irix*) # IRIX has differently named shared libraries - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_irix.o" - WINBIND_NSS="nsswitch/libns_winbind.$SHLIBEXT" - WINBIND_WINS_NSS="nsswitch/libns_wins.$SHLIBEXT" + WINBIND_NSS_EXTRA_OBJS="../nsswitch/winbind_nss_irix.o" + WINBIND_NSS="../nsswitch/libns_winbind.$SHLIBEXT" + WINBIND_WINS_NSS="../nsswitch/libns_wins.$SHLIBEXT" ;; *solaris*) # Solaris winbind client is implemented as a wrapper around # the Linux version. NSSSONAMEVERSIONSUFFIX=".1" - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o \ - nsswitch/winbind_nss_linux.o" + WINBIND_NSS_EXTRA_OBJS="../nsswitch/winbind_nss_solaris.o \ + ../nsswitch/winbind_nss_linux.o" WINBIND_NSS_EXTRA_LIBS="${LIBREPLACE_NETWORK_LIBS}" PAM_WINBIND_EXTRA_LIBS="${LIBREPLACE_NETWORK_LIBS}" ;; *hpux11*) - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o" + WINBIND_NSS_EXTRA_OBJS="../nsswitch/winbind_nss_solaris.o" ;; *aix*) # AIX has even differently named shared libraries. No # WINS support has been implemented yet. - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_aix.o" + WINBIND_NSS_EXTRA_OBJS="../nsswitch/winbind_nss_aix.o" WINBIND_NSS_LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-ewb_aix_init" - WINBIND_NSS="nsswitch/WINBIND" + WINBIND_NSS="../nsswitch/WINBIND" WINBIND_WINS_NSS="" ;; *) diff --git a/source3/nsswitch/libwbclient/Doxyfile b/source3/nsswitch/libwbclient/Doxyfile deleted file mode 100644 index e12c2b06f0..0000000000 --- a/source3/nsswitch/libwbclient/Doxyfile +++ /dev/null @@ -1,1297 +0,0 @@ -# Doxyfile 1.5.3 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file that -# follow. The default is UTF-8 which is also the encoding used for all text before -# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into -# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of -# possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Samba - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = HEAD - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = dox - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, -# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, -# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, -# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = $(PWD)/ - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to -# include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be extracted -# and appear in the documentation as a namespace called 'anonymous_namespace{file}', -# where file will be replaced with the base name of the file that contains the anonymous -# namespace. By default anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from the -# version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = NO - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = NO - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text " - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . - -# This tag can be used to specify the character encoding of the source files that -# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default -# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. -# See http://www.gnu.org/software/libiconv for the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py - -FILE_PATTERNS = *.c \ - *.h \ - *.idl - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = include/includes.h \ - include/proto.h - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the output. -# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, -# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH -# then you must also enable this option. If you don't then doxygen will produce -# a warning and turn it on anyway - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = YES - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 1 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = . - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 3 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = YES - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = NO - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to -# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to -# specify the directory where the mscgen tool resides. If left empty the tool is assumed to -# be found in the default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will -# generate a caller dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the number -# of direct children of the root node in a graph is already larger than -# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, which results in a white background. -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/source3/nsswitch/libwbclient/libwbclient.h b/source3/nsswitch/libwbclient/libwbclient.h deleted file mode 100644 index 74cba7e796..0000000000 --- a/source3/nsswitch/libwbclient/libwbclient.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _LIBWBCLIENT_H -#define _LIBWBCLIENT_H - -/* Super header including necessary public and private header files - for building the wbclient library. __DO NOT__ define anything - in this file. Only include other headers. */ - -/* Winbind headers */ - -#include "nsswitch/winbind_nss_config.h" -#include "nsswitch/winbind_struct_protocol.h" - -#include - -/* Public headers */ - -#include "wbclient.h" - -/* Private headers */ - -#include "wbc_err_internal.h" -#include "wbclient_internal.h" - - -#endif /* _LIBWBCLIENT_H */ diff --git a/source3/nsswitch/libwbclient/wbc_err_internal.h b/source3/nsswitch/libwbclient/wbc_err_internal.h deleted file mode 100644 index 83364b8cd9..0000000000 --- a/source3/nsswitch/libwbclient/wbc_err_internal.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WBC_ERR_INTERNAL_H -#define _WBC_ERR_INTERNAL_H - -/* Private macros */ - -#define BAIL_ON_WBC_ERROR(x) \ - do { \ - if (!WBC_ERROR_IS_OK(x)) { \ - goto done; \ - } \ - } while(0); - -#define BAIL_ON_PTR_ERROR(x, status) \ - do { \ - if ((x) == NULL) { \ - status = WBC_ERR_NO_MEMORY; \ - goto done; \ - } else { \ - status = WBC_ERR_SUCCESS; \ - } \ - } while (0); - - -#endif /* _WBC_ERR_INTERNAL_H */ diff --git a/source3/nsswitch/libwbclient/wbc_guid.c b/source3/nsswitch/libwbclient/wbc_guid.c deleted file mode 100644 index c343e24351..0000000000 --- a/source3/nsswitch/libwbclient/wbc_guid.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - -/* Convert a binary GUID to a character string */ -wbcErr wbcGuidToString(const struct wbcGuid *guid, - char **guid_string) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!guid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - *guid_string = talloc_asprintf(NULL, - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - guid->time_low, guid->time_mid, - guid->time_hi_and_version, - guid->clock_seq[0], - guid->clock_seq[1], - guid->node[0], guid->node[1], - guid->node[2], guid->node[3], - guid->node[4], guid->node[5]); - BAIL_ON_PTR_ERROR((*guid_string), wbc_status); - - wbc_status = WBC_ERR_SUCCESS; - -done: - return wbc_status; -} - -/* @brief Convert a character string to a binary GUID */ -wbcErr wbcStringToGuid(const char *str, - struct wbcGuid *guid) -{ - uint32_t time_low; - uint32_t time_mid, time_hi_and_version; - uint32_t clock_seq[2]; - uint32_t node[6]; - int i; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!guid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (!str) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (11 == sscanf(str, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - &time_low, &time_mid, &time_hi_and_version, - &clock_seq[0], &clock_seq[1], - &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { - wbc_status = WBC_ERR_SUCCESS; - } else if (11 == sscanf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - &time_low, &time_mid, &time_hi_and_version, - &clock_seq[0], &clock_seq[1], - &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { - wbc_status = WBC_ERR_SUCCESS; - } - - BAIL_ON_WBC_ERROR(wbc_status); - - guid->time_low = time_low; - guid->time_mid = time_mid; - guid->time_hi_and_version = time_hi_and_version; - guid->clock_seq[0] = clock_seq[0]; - guid->clock_seq[1] = clock_seq[1]; - - for (i=0;i<6;i++) { - guid->node[i] = node[i]; - } - - wbc_status = WBC_ERR_SUCCESS; - -done: - return wbc_status; -} diff --git a/source3/nsswitch/libwbclient/wbc_idmap.c b/source3/nsswitch/libwbclient/wbc_idmap.c deleted file mode 100644 index 5b2ab875f6..0000000000 --- a/source3/nsswitch/libwbclient/wbc_idmap.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - -/* Convert a Windows SID to a Unix uid, allocating an uid if needed */ -wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid) -{ - struct winbindd_request request; - struct winbindd_response response; - char *sid_string = NULL; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!sid || !puid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); - wbcFreeMemory(sid_string); - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_SID_TO_UID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - *puid = response.data.uid; - - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* Convert a Windows SID to a Unix uid if there already is a mapping */ -wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid, - uid_t *puid) -{ - return WBC_ERR_NOT_IMPLEMENTED; -} - -/* Convert a Unix uid to a Windows SID, allocating a SID if needed */ -wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - - if (!sid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.uid = uid; - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_UID_TO_SID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - wbc_status = wbcStringToSid(response.data.sid.sid, sid); - BAIL_ON_WBC_ERROR(wbc_status); - -done: - return wbc_status; -} - -/* Convert a Unix uid to a Windows SID if there already is a mapping */ -wbcErr wbcQueryUidToSid(uid_t uid, - struct wbcDomainSid *sid) -{ - return WBC_ERR_NOT_IMPLEMENTED; -} - -/** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed - * - * @param *sid Pointer to the domain SID to be resolved - * @param *pgid Pointer to the resolved gid_t value - * - * @return #wbcErr - * - **/ - -wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *sid_string = NULL; - - if (!sid || !pgid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); - wbcFreeMemory(sid_string); - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_SID_TO_GID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - *pgid = response.data.gid; - - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* Convert a Windows SID to a Unix gid if there already is a mapping */ - -wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid, - gid_t *pgid) -{ - return WBC_ERR_NOT_IMPLEMENTED; -} - -/* Convert a Unix gid to a Windows SID, allocating a SID if needed */ -wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!sid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.gid = gid; - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_GID_TO_SID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - wbc_status = wbcStringToSid(response.data.sid.sid, sid); - BAIL_ON_WBC_ERROR(wbc_status); - -done: - return wbc_status; -} - -/* Convert a Unix gid to a Windows SID if there already is a mapping */ -wbcErr wbcQueryGidToSid(gid_t gid, - struct wbcDomainSid *sid) -{ - return WBC_ERR_NOT_IMPLEMENTED; -} - -/* Obtain a new uid from Winbind */ -wbcErr wbcAllocateUid(uid_t *puid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!puid) - return WBC_ERR_INVALID_PARAM; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_ALLOCATE_UID, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Copy out result */ - *puid = response.data.uid; - - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* Obtain a new gid from Winbind */ -wbcErr wbcAllocateGid(gid_t *pgid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!pgid) - return WBC_ERR_INVALID_PARAM; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_ALLOCATE_GID, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Copy out result */ - *pgid = response.data.gid; - - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* we can't include smb.h here... */ -#define _ID_TYPE_UID 1 -#define _ID_TYPE_GID 2 - -/* Set an user id mapping */ -wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *sid_string = NULL; - - if (!sid) { - return WBC_ERR_INVALID_PARAM; - } - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - request.data.dual_idmapset.id = uid; - request.data.dual_idmapset.type = _ID_TYPE_UID; - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.dual_idmapset.sid, sid_string, - sizeof(request.data.dual_idmapset.sid)-1); - wbcFreeMemory(sid_string); - - wbc_status = wbcRequestResponse(WINBINDD_SET_MAPPING, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Set a group id mapping */ -wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *sid_string = NULL; - - if (!sid) { - return WBC_ERR_INVALID_PARAM; - } - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - request.data.dual_idmapset.id = gid; - request.data.dual_idmapset.type = _ID_TYPE_GID; - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.dual_idmapset.sid, sid_string, - sizeof(request.data.dual_idmapset.sid)-1); - wbcFreeMemory(sid_string); - - wbc_status = wbcRequestResponse(WINBINDD_SET_MAPPING, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Remove a user id mapping */ -wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *sid_string = NULL; - - if (!sid) { - return WBC_ERR_INVALID_PARAM; - } - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - request.data.dual_idmapset.id = uid; - request.data.dual_idmapset.type = _ID_TYPE_UID; - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.dual_idmapset.sid, sid_string, - sizeof(request.data.dual_idmapset.sid)-1); - wbcFreeMemory(sid_string); - - wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Remove a group id mapping */ -wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *sid_string = NULL; - - if (!sid) { - return WBC_ERR_INVALID_PARAM; - } - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - request.data.dual_idmapset.id = gid; - request.data.dual_idmapset.type = _ID_TYPE_GID; - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.dual_idmapset.sid, sid_string, - sizeof(request.data.dual_idmapset.sid)-1); - wbcFreeMemory(sid_string); - - wbc_status = wbcRequestResponse(WINBINDD_REMOVE_MAPPING, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Set the highwater mark for allocated uids. */ -wbcErr wbcSetUidHwm(uid_t uid_hwm) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - request.data.dual_idmapset.id = uid_hwm; - request.data.dual_idmapset.type = _ID_TYPE_UID; - - wbc_status = wbcRequestResponse(WINBINDD_SET_HWM, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Set the highwater mark for allocated gids. */ -wbcErr wbcSetGidHwm(gid_t gid_hwm) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Make request */ - - request.data.dual_idmapset.id = gid_hwm; - request.data.dual_idmapset.type = _ID_TYPE_GID; - - wbc_status = wbcRequestResponse(WINBINDD_SET_HWM, - &request, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} diff --git a/source3/nsswitch/libwbclient/wbc_pam.c b/source3/nsswitch/libwbclient/wbc_pam.c deleted file mode 100644 index 92c6643631..0000000000 --- a/source3/nsswitch/libwbclient/wbc_pam.c +++ /dev/null @@ -1,1034 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - Copyright (C) Guenther Deschner 2008 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - -/* Authenticate a username/password pair */ -wbcErr wbcAuthenticateUser(const char *username, - const char *password) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcAuthUserParams params; - - ZERO_STRUCT(params); - - params.account_name = username; - params.level = WBC_AUTH_USER_LEVEL_PLAIN; - params.password.plaintext = password; - - wbc_status = wbcAuthenticateUserEx(¶ms, NULL, NULL); - BAIL_ON_WBC_ERROR(wbc_status); - -done: - return wbc_status; -} - -static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx, - const struct winbindd_response *resp, - struct wbcAuthUserInfo **_i) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcAuthUserInfo *i; - struct wbcDomainSid domain_sid; - char *p; - uint32_t sn = 0; - uint32_t j; - - i = talloc(mem_ctx, struct wbcAuthUserInfo); - BAIL_ON_PTR_ERROR(i, wbc_status); - - i->user_flags = resp->data.auth.info3.user_flgs; - - i->account_name = talloc_strdup(i, resp->data.auth.info3.user_name); - BAIL_ON_PTR_ERROR(i->account_name, wbc_status); - i->user_principal= NULL; - i->full_name = talloc_strdup(i, resp->data.auth.info3.full_name); - BAIL_ON_PTR_ERROR(i->full_name, wbc_status); - i->domain_name = talloc_strdup(i, resp->data.auth.info3.logon_dom); - BAIL_ON_PTR_ERROR(i->domain_name, wbc_status); - i->dns_domain_name= NULL; - - i->acct_flags = resp->data.auth.info3.acct_flags; - memcpy(i->user_session_key, - resp->data.auth.user_session_key, - sizeof(i->user_session_key)); - memcpy(i->lm_session_key, - resp->data.auth.first_8_lm_hash, - sizeof(i->lm_session_key)); - - i->logon_count = resp->data.auth.info3.logon_count; - i->bad_password_count = resp->data.auth.info3.bad_pw_count; - - i->logon_time = resp->data.auth.info3.logon_time; - i->logoff_time = resp->data.auth.info3.logoff_time; - i->kickoff_time = resp->data.auth.info3.kickoff_time; - i->pass_last_set_time = resp->data.auth.info3.pass_last_set_time; - i->pass_can_change_time = resp->data.auth.info3.pass_can_change_time; - i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time; - - i->logon_server = talloc_strdup(i, resp->data.auth.info3.logon_srv); - BAIL_ON_PTR_ERROR(i->logon_server, wbc_status); - i->logon_script = talloc_strdup(i, resp->data.auth.info3.logon_script); - BAIL_ON_PTR_ERROR(i->logon_script, wbc_status); - i->profile_path = talloc_strdup(i, resp->data.auth.info3.profile_path); - BAIL_ON_PTR_ERROR(i->profile_path, wbc_status); - i->home_directory= talloc_strdup(i, resp->data.auth.info3.home_dir); - BAIL_ON_PTR_ERROR(i->home_directory, wbc_status); - i->home_drive = talloc_strdup(i, resp->data.auth.info3.dir_drive); - BAIL_ON_PTR_ERROR(i->home_drive, wbc_status); - - i->num_sids = 2; - i->num_sids += resp->data.auth.info3.num_groups; - i->num_sids += resp->data.auth.info3.num_other_sids; - - i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids); - BAIL_ON_PTR_ERROR(i->sids, wbc_status); - - wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid, - &domain_sid); - BAIL_ON_WBC_ERROR(wbc_status); - -#define _SID_COMPOSE(s, d, r, a) { \ - (s).sid = d; \ - if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \ - (s).sid.sub_auths[(s).sid.num_auths++] = r; \ - } else { \ - wbc_status = WBC_ERR_INVALID_SID; \ - BAIL_ON_WBC_ERROR(wbc_status); \ - } \ - (s).attributes = a; \ -} while (0) - - sn = 0; - _SID_COMPOSE(i->sids[sn], domain_sid, - resp->data.auth.info3.user_rid, - 0); - sn++; - _SID_COMPOSE(i->sids[sn], domain_sid, - resp->data.auth.info3.group_rid, - 0); - sn++; - - p = (char *)resp->extra_data.data; - if (!p) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - - for (j=0; j < resp->data.auth.info3.num_groups; j++) { - uint32_t rid; - uint32_t attrs; - int ret; - char *s = p; - char *e = strchr(p, '\n'); - if (!e) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - e[0] = '\0'; - p = &e[1]; - - ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs); - if (ret != 2) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - - _SID_COMPOSE(i->sids[sn], domain_sid, - rid, attrs); - sn++; - } - - for (j=0; j < resp->data.auth.info3.num_other_sids; j++) { - uint32_t attrs; - int ret; - char *s = p; - char *a; - char *e = strchr(p, '\n'); - if (!e) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - e[0] = '\0'; - p = &e[1]; - - e = strchr(s, ':'); - if (!e) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - e[0] = '\0'; - a = &e[1]; - - ret = sscanf(a, "0x%08X", - &attrs); - if (ret != 1) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = wbcStringToSid(s, &i->sids[sn].sid); - BAIL_ON_WBC_ERROR(wbc_status); - - i->sids[sn].attributes = attrs; - sn++; - } - - i->num_sids = sn; - - *_i = i; - i = NULL; -done: - talloc_free(i); - return wbc_status; -} - -static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx, - const struct winbindd_response *resp, - struct wbcAuthErrorInfo **_e) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcAuthErrorInfo *e; - - e = talloc(mem_ctx, struct wbcAuthErrorInfo); - BAIL_ON_PTR_ERROR(e, wbc_status); - - e->nt_status = resp->data.auth.nt_status; - e->pam_error = resp->data.auth.pam_error; - e->nt_string = talloc_strdup(e, resp->data.auth.nt_status_string); - BAIL_ON_PTR_ERROR(e->nt_string, wbc_status); - - e->display_string = talloc_strdup(e, resp->data.auth.error_string); - BAIL_ON_PTR_ERROR(e->display_string, wbc_status); - - *_e = e; - e = NULL; - -done: - talloc_free(e); - return wbc_status; -} - -static wbcErr wbc_create_password_policy_info(TALLOC_CTX *mem_ctx, - const struct winbindd_response *resp, - struct wbcUserPasswordPolicyInfo **_i) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcUserPasswordPolicyInfo *i; - - i = talloc(mem_ctx, struct wbcUserPasswordPolicyInfo); - BAIL_ON_PTR_ERROR(i, wbc_status); - - i->min_passwordage = resp->data.auth.policy.min_passwordage; - i->min_length_password = resp->data.auth.policy.min_length_password; - i->password_history = resp->data.auth.policy.password_history; - i->password_properties = resp->data.auth.policy.password_properties; - i->expire = resp->data.auth.policy.expire; - - *_i = i; - i = NULL; - -done: - talloc_free(i); - return wbc_status; -} - -static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx, - const struct winbindd_response *resp, - struct wbcLogonUserInfo **_i) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcLogonUserInfo *i; - - i = talloc_zero(mem_ctx, struct wbcLogonUserInfo); - BAIL_ON_PTR_ERROR(i, wbc_status); - - wbc_status = wbc_create_auth_info(i, resp, &i->info); - BAIL_ON_WBC_ERROR(wbc_status); - - if (resp->data.auth.krb5ccname) { - wbc_status = wbcAddNamedBlob(&i->num_blobs, - &i->blobs, - "krb5ccname", - 0, - (uint8_t *)resp->data.auth.krb5ccname, - strlen(resp->data.auth.krb5ccname)+1); - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (resp->data.auth.unix_username) { - wbc_status = wbcAddNamedBlob(&i->num_blobs, - &i->blobs, - "unix_username", - 0, - (uint8_t *)resp->data.auth.unix_username, - strlen(resp->data.auth.unix_username)+1); - BAIL_ON_WBC_ERROR(wbc_status); - } - - *_i = i; - i = NULL; -done: - if (!WBC_ERROR_IS_OK(wbc_status) && i) { - wbcFreeMemory(i->blobs); - } - - talloc_free(i); - return wbc_status; -} - -/* Authenticate with more detailed information */ -wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params, - struct wbcAuthUserInfo **info, - struct wbcAuthErrorInfo **error) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - int cmd = 0; - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (error) { - *error = NULL; - } - - if (!params) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (!params->account_name) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - switch (params->level) { - case WBC_AUTH_USER_LEVEL_PLAIN: - cmd = WINBINDD_PAM_AUTH; - request.flags = WBFLAG_PAM_INFO3_TEXT | - WBFLAG_PAM_USER_SESSION_KEY | - WBFLAG_PAM_LMKEY; - - if (!params->password.plaintext) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->domain_name && params->domain_name[0]) { - /* We need to get the winbind separator :-( */ - struct winbindd_response sep_response; - - ZERO_STRUCT(sep_response); - - wbc_status = wbcRequestResponse(WINBINDD_INFO, - NULL, &sep_response); - BAIL_ON_WBC_ERROR(wbc_status); - - snprintf(request.data.auth.user, - sizeof(request.data.auth.user)-1, - "%s%c%s", - params->domain_name, - sep_response.data.info.winbind_separator, - params->account_name); - } else { - strncpy(request.data.auth.user, - params->account_name, - sizeof(request.data.auth.user)-1); - } - - strncpy(request.data.auth.pass, - params->password.plaintext, - sizeof(request.data.auth.pass)-1); - break; - - case WBC_AUTH_USER_LEVEL_HASH: - wbc_status = WBC_ERR_NOT_IMPLEMENTED; - BAIL_ON_WBC_ERROR(wbc_status); - break; - - case WBC_AUTH_USER_LEVEL_RESPONSE: - cmd = WINBINDD_PAM_AUTH_CRAP; - request.flags = WBFLAG_PAM_INFO3_TEXT | - WBFLAG_PAM_USER_SESSION_KEY | - WBFLAG_PAM_LMKEY; - - if (params->password.response.lm_length && - !params->password.response.lm_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - if (params->password.response.lm_length == 0 && - params->password.response.lm_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->password.response.nt_length && - !params->password.response.nt_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - if (params->password.response.nt_length == 0&& - params->password.response.nt_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - strncpy(request.data.auth_crap.user, - params->account_name, - sizeof(request.data.auth_crap.user)-1); - if (params->domain_name) { - strncpy(request.data.auth_crap.domain, - params->domain_name, - sizeof(request.data.auth_crap.domain)-1); - } - if (params->workstation_name) { - strncpy(request.data.auth_crap.workstation, - params->workstation_name, - sizeof(request.data.auth_crap.workstation)-1); - } - - request.data.auth_crap.logon_parameters = - params->parameter_control; - - memcpy(request.data.auth_crap.chal, - params->password.response.challenge, - sizeof(request.data.auth_crap.chal)); - - request.data.auth_crap.lm_resp_len = - MIN(params->password.response.lm_length, - sizeof(request.data.auth_crap.lm_resp)); - request.data.auth_crap.nt_resp_len = - MIN(params->password.response.nt_length, - sizeof(request.data.auth_crap.nt_resp)); - if (params->password.response.lm_data) { - memcpy(request.data.auth_crap.lm_resp, - params->password.response.lm_data, - request.data.auth_crap.lm_resp_len); - } - if (params->password.response.nt_data) { - memcpy(request.data.auth_crap.nt_resp, - params->password.response.nt_data, - request.data.auth_crap.nt_resp_len); - } - break; - default: - break; - } - - if (cmd == 0) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->flags) { - request.flags |= params->flags; - } - - wbc_status = wbcRequestResponse(cmd, - &request, - &response); - if (response.data.auth.nt_status != 0) { - if (error) { - wbc_status = wbc_create_error_info(NULL, - &response, - error); - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = WBC_ERR_AUTH_ERROR; - BAIL_ON_WBC_ERROR(wbc_status); - } - BAIL_ON_WBC_ERROR(wbc_status); - - if (info) { - wbc_status = wbc_create_auth_info(NULL, - &response, - info); - BAIL_ON_WBC_ERROR(wbc_status); - } - -done: - if (response.extra_data.data) - free(response.extra_data.data); - - return wbc_status; -} - -/* Trigger a verification of the trust credentials of a specific domain */ -wbcErr wbcCheckTrustCredentials(const char *domain, - struct wbcAuthErrorInfo **error) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (domain) { - /* - * the current protocol doesn't support - * specifying a domain - */ - wbc_status = WBC_ERR_NOT_IMPLEMENTED; - BAIL_ON_WBC_ERROR(wbc_status); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC, - &request, - &response); - if (response.data.auth.nt_status != 0) { - if (error) { - wbc_status = wbc_create_error_info(NULL, - &response, - error); - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = WBC_ERR_AUTH_ERROR; - BAIL_ON_WBC_ERROR(wbc_status); - } - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Trigger an extended logoff notification to Winbind for a specific user */ -wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params, - struct wbcAuthErrorInfo **error) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - int i; - - /* validate input */ - - if (!params || !params->username) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if ((params->num_blobs > 0) && (params->blobs == NULL)) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - if ((params->num_blobs == 0) && (params->blobs != NULL)) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.logoff.user, params->username, - sizeof(request.data.logoff.user)-1); - - for (i=0; inum_blobs; i++) { - - if (strcasecmp(params->blobs[i].name, "ccfilename") == 0) { - if (params->blobs[i].blob.data) { - strncpy(request.data.logoff.krb5ccname, - (const char *)params->blobs[i].blob.data, - sizeof(request.data.logoff.krb5ccname) - 1); - } - continue; - } - - if (strcasecmp(params->blobs[i].name, "user_uid") == 0) { - if (params->blobs[i].blob.data) { - memcpy(&request.data.logoff.uid, - params->blobs[i].blob.data, - MIN(params->blobs[i].blob.length, - sizeof(request.data.logoff.uid))); - } - continue; - } - - if (strcasecmp(params->blobs[i].name, "flags") == 0) { - if (params->blobs[i].blob.data) { - memcpy(&request.flags, - params->blobs[i].blob.data, - MIN(params->blobs[i].blob.length, - sizeof(request.flags))); - } - continue; - } - } - - /* Send request */ - - wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF, - &request, - &response); - - /* Take the response above and return it to the caller */ - if (response.data.auth.nt_status != 0) { - if (error) { - wbc_status = wbc_create_error_info(NULL, - &response, - error); - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = WBC_ERR_AUTH_ERROR; - BAIL_ON_WBC_ERROR(wbc_status); - } - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Trigger a logoff notification to Winbind for a specific user */ -wbcErr wbcLogoffUser(const char *username, - uid_t uid, - const char *ccfilename) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - /* validate input */ - - if (!username) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.logoff.user, username, - sizeof(request.data.logoff.user)-1); - request.data.logoff.uid = uid; - - if (ccfilename) { - strncpy(request.data.logoff.krb5ccname, ccfilename, - sizeof(request.data.logoff.krb5ccname)-1); - } - - /* Send request */ - - wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF, - &request, - &response); - - /* Take the response above and return it to the caller */ - - done: - return wbc_status; -} - -/* Change a password for a user with more detailed information upon failure */ -wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params, - struct wbcAuthErrorInfo **error, - enum wbcPasswordChangeRejectReason *reject_reason, - struct wbcUserPasswordPolicyInfo **policy) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - int cmd = 0; - - /* validate input */ - - if (!params->account_name) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (error) { - *error = NULL; - } - - if (policy) { - *policy = NULL; - } - - if (reject_reason) { - *reject_reason = -1; - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - switch (params->level) { - case WBC_CHANGE_PASSWORD_LEVEL_PLAIN: - cmd = WINBINDD_PAM_CHAUTHTOK; - - if (!params->account_name) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - strncpy(request.data.chauthtok.user, params->account_name, - sizeof(request.data.chauthtok.user) - 1); - - if (params->old_password.plaintext) { - strncpy(request.data.chauthtok.oldpass, - params->old_password.plaintext, - sizeof(request.data.chauthtok.oldpass) - 1); - } - - if (params->new_password.plaintext) { - strncpy(request.data.chauthtok.newpass, - params->new_password.plaintext, - sizeof(request.data.chauthtok.newpass) - 1); - } - break; - - case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE: - cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP; - - if (!params->account_name || !params->domain_name) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->old_password.response.old_lm_hash_enc_length && - !params->old_password.response.old_lm_hash_enc_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->old_password.response.old_lm_hash_enc_length == 0 && - params->old_password.response.old_lm_hash_enc_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->old_password.response.old_nt_hash_enc_length && - !params->old_password.response.old_nt_hash_enc_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->old_password.response.old_nt_hash_enc_length == 0 && - params->old_password.response.old_nt_hash_enc_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->new_password.response.lm_length && - !params->new_password.response.lm_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->new_password.response.lm_length == 0 && - params->new_password.response.lm_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->new_password.response.nt_length && - !params->new_password.response.nt_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (params->new_password.response.nt_length == 0 && - params->new_password.response.nt_data) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - strncpy(request.data.chng_pswd_auth_crap.user, - params->account_name, - sizeof(request.data.chng_pswd_auth_crap.user) - 1); - - strncpy(request.data.chng_pswd_auth_crap.domain, - params->domain_name, - sizeof(request.data.chng_pswd_auth_crap.domain) - 1); - - if (params->new_password.response.nt_data) { - memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd, - params->new_password.response.nt_data, - request.data.chng_pswd_auth_crap.new_nt_pswd_len); - request.data.chng_pswd_auth_crap.new_nt_pswd_len = - params->new_password.response.nt_length; - } - - if (params->new_password.response.lm_data) { - memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd, - params->new_password.response.lm_data, - request.data.chng_pswd_auth_crap.new_lm_pswd_len); - request.data.chng_pswd_auth_crap.new_lm_pswd_len = - params->new_password.response.lm_length; - } - - if (params->old_password.response.old_nt_hash_enc_data) { - memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc, - params->old_password.response.old_nt_hash_enc_data, - request.data.chng_pswd_auth_crap.old_nt_hash_enc_len); - request.data.chng_pswd_auth_crap.old_nt_hash_enc_len = - params->old_password.response.old_nt_hash_enc_length; - } - - if (params->old_password.response.old_lm_hash_enc_data) { - memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc, - params->old_password.response.old_lm_hash_enc_data, - request.data.chng_pswd_auth_crap.old_lm_hash_enc_len); - request.data.chng_pswd_auth_crap.old_lm_hash_enc_len = - params->old_password.response.old_lm_hash_enc_length; - } - - break; - default: - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - break; - } - - if (cmd == 0) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Send request */ - - wbc_status = wbcRequestResponse(cmd, - &request, - &response); - if (WBC_ERROR_IS_OK(wbc_status)) { - goto done; - } - - /* Take the response above and return it to the caller */ - - if (response.data.auth.nt_status != 0) { - if (error) { - wbc_status = wbc_create_error_info(NULL, - &response, - error); - BAIL_ON_WBC_ERROR(wbc_status); - } - - } - - if (policy) { - wbc_status = wbc_create_password_policy_info(NULL, - &response, - policy); - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (reject_reason) { - *reject_reason = response.data.auth.reject_reason; - } - - wbc_status = WBC_ERR_PWD_CHANGE_FAILED; - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Change a password for a user */ -wbcErr wbcChangeUserPassword(const char *username, - const char *old_password, - const char *new_password) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcChangePasswordParams params; - - ZERO_STRUCT(params); - - params.account_name = username; - params.level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN; - params.old_password.plaintext = old_password; - params.new_password.plaintext = new_password; - - wbc_status = wbcChangeUserPasswordEx(¶ms, - NULL, - NULL, - NULL); - BAIL_ON_WBC_ERROR(wbc_status); - -done: - return wbc_status; -} - -/* Logon a User */ -wbcErr wbcLogonUser(const struct wbcLogonUserParams *params, - struct wbcLogonUserInfo **info, - struct wbcAuthErrorInfo **error, - struct wbcUserPasswordPolicyInfo **policy) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - int cmd = 0; - struct winbindd_request request; - struct winbindd_response response; - uint32_t i; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (info) { - *info = NULL; - } - if (error) { - *error = NULL; - } - if (policy) { - *policy = NULL; - } - - if (!params) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (!params->username) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - if ((params->num_blobs > 0) && (params->blobs == NULL)) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - if ((params->num_blobs == 0) && (params->blobs != NULL)) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - cmd = WINBINDD_PAM_AUTH; - request.flags = WBFLAG_PAM_INFO3_TEXT | - WBFLAG_PAM_USER_SESSION_KEY | - WBFLAG_PAM_LMKEY; - - if (!params->password) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - strncpy(request.data.auth.user, - params->username, - sizeof(request.data.auth.user)-1); - - strncpy(request.data.auth.pass, - params->password, - sizeof(request.data.auth.pass)-1); - - for (i=0; inum_blobs; i++) { - - if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) { - if (params->blobs[i].blob.data) { - strncpy(request.data.auth.krb5_cc_type, - (const char *)params->blobs[i].blob.data, - sizeof(request.data.auth.krb5_cc_type) - 1); - } - continue; - } - - if (strcasecmp(params->blobs[i].name, "user_uid") == 0) { - if (params->blobs[i].blob.data) { - memcpy(&request.data.auth.uid, - params->blobs[i].blob.data, - MIN(sizeof(request.data.auth.uid), - params->blobs[i].blob.length)); - } - continue; - } - - if (strcasecmp(params->blobs[i].name, "flags") == 0) { - if (params->blobs[i].blob.data) { - uint32_t flags; - memcpy(&flags, - params->blobs[i].blob.data, - MIN(sizeof(flags), - params->blobs[i].blob.length)); - request.flags |= flags; - } - continue; - } - - if (strcasecmp(params->blobs[i].name, "membership_of") == 0) { - if (params->blobs[i].blob.data && - params->blobs[i].blob.data[0] > 0) { - strncpy(request.data.auth.require_membership_of_sid, - (const char *)params->blobs[i].blob.data, - sizeof(request.data.auth.require_membership_of_sid) - 1); - } - continue; - } - } - - wbc_status = wbcRequestResponse(cmd, - &request, - &response); - - if (response.data.auth.nt_status != 0) { - if (error) { - wbc_status = wbc_create_error_info(NULL, - &response, - error); - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = WBC_ERR_AUTH_ERROR; - BAIL_ON_WBC_ERROR(wbc_status); - } - BAIL_ON_WBC_ERROR(wbc_status); - - if (info) { - wbc_status = wbc_create_logon_info(NULL, - &response, - info); - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (policy) { - wbc_status = wbc_create_password_policy_info(NULL, - &response, - policy); - BAIL_ON_WBC_ERROR(wbc_status); - } - -done: - if (response.extra_data.data) - free(response.extra_data.data); - - return wbc_status; -} - -/* Authenticate a user with cached credentials */ -wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params, - struct wbcCredentialCacheInfo **info, - struct wbcAuthErrorInfo **error) -{ - return WBC_ERR_NOT_IMPLEMENTED; -} diff --git a/source3/nsswitch/libwbclient/wbc_pwd.c b/source3/nsswitch/libwbclient/wbc_pwd.c deleted file mode 100644 index cd945996c8..0000000000 --- a/source3/nsswitch/libwbclient/wbc_pwd.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - -/** @brief The maximum number of pwent structs to get from winbindd - * - */ -#define MAX_GETPWENT_USERS 500 - -/** @brief The maximum number of grent structs to get from winbindd - * - */ -#define MAX_GETGRENT_GROUPS 500 - -/** - * - **/ - -static struct passwd *copy_passwd_entry(struct winbindd_pw *p) -{ - struct passwd *pwd = NULL; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - pwd = talloc(NULL, struct passwd); - BAIL_ON_PTR_ERROR(pwd, wbc_status); - - pwd->pw_name = talloc_strdup(pwd,p->pw_name); - BAIL_ON_PTR_ERROR(pwd->pw_name, wbc_status); - - pwd->pw_passwd = talloc_strdup(pwd, p->pw_passwd); - BAIL_ON_PTR_ERROR(pwd->pw_passwd, wbc_status); - - pwd->pw_gecos = talloc_strdup(pwd, p->pw_gecos); - BAIL_ON_PTR_ERROR(pwd->pw_gecos, wbc_status); - - pwd->pw_shell = talloc_strdup(pwd, p->pw_shell); - BAIL_ON_PTR_ERROR(pwd->pw_shell, wbc_status); - - pwd->pw_dir = talloc_strdup(pwd, p->pw_dir); - BAIL_ON_PTR_ERROR(pwd->pw_dir, wbc_status); - - pwd->pw_uid = p->pw_uid; - pwd->pw_gid = p->pw_gid; - -done: - if (!WBC_ERROR_IS_OK(wbc_status)) { - talloc_free(pwd); - pwd = NULL; - } - - return pwd; -} - -/** - * - **/ - -static struct group *copy_group_entry(struct winbindd_gr *g, - char *mem_buf) -{ - struct group *grp = NULL; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - int i; - char *mem_p, *mem_q; - - grp = talloc(NULL, struct group); - BAIL_ON_PTR_ERROR(grp, wbc_status); - - grp->gr_name = talloc_strdup(grp, g->gr_name); - BAIL_ON_PTR_ERROR(grp->gr_name, wbc_status); - - grp->gr_passwd = talloc_strdup(grp, g->gr_passwd); - BAIL_ON_PTR_ERROR(grp->gr_passwd, wbc_status); - - grp->gr_gid = g->gr_gid; - - grp->gr_mem = talloc_array(grp, char*, g->num_gr_mem+1); - - mem_p = mem_q = mem_buf; - for (i=0; inum_gr_mem && mem_p; i++) { - if ((mem_q = strchr(mem_p, ',')) != NULL) { - *mem_q = '\0'; - } - - grp->gr_mem[i] = talloc_strdup(grp, mem_p); - BAIL_ON_PTR_ERROR(grp->gr_mem[i], wbc_status); - - if (mem_q == NULL) { - i += 1; - break; - } - mem_p = mem_q + 1; - } - grp->gr_mem[i] = NULL; - - wbc_status = WBC_ERR_SUCCESS; - -done: - if (!WBC_ERROR_IS_OK(wbc_status)) { - talloc_free(grp); - grp = NULL; - } - - return grp; -} - -/* Fill in a struct passwd* for a domain user based on username */ -wbcErr wbcGetpwnam(const char *name, struct passwd **pwd) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - - if (!name || !pwd) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* dst is already null terminated from the memset above */ - - strncpy(request.data.username, name, sizeof(request.data.username)-1); - - wbc_status = wbcRequestResponse(WINBINDD_GETPWNAM, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - *pwd = copy_passwd_entry(&response.data.pw); - BAIL_ON_PTR_ERROR(*pwd, wbc_status); - - done: - return wbc_status; -} - -/* Fill in a struct passwd* for a domain user based on uid */ -wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - - if (!pwd) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.uid = uid; - - wbc_status = wbcRequestResponse(WINBINDD_GETPWUID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - *pwd = copy_passwd_entry(&response.data.pw); - BAIL_ON_PTR_ERROR(*pwd, wbc_status); - - done: - return wbc_status; -} - -/* Fill in a struct passwd* for a domain user based on username */ -wbcErr wbcGetgrnam(const char *name, struct group **grp) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (!name || !grp) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* dst is already null terminated from the memset above */ - - strncpy(request.data.groupname, name, sizeof(request.data.groupname)-1); - - wbc_status = wbcRequestResponse(WINBINDD_GETGRNAM, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - *grp = copy_group_entry(&response.data.gr, - (char*)response.extra_data.data); - BAIL_ON_PTR_ERROR(*grp, wbc_status); - - done: - if (response.extra_data.data) - free(response.extra_data.data); - - return wbc_status; -} - -/* Fill in a struct passwd* for a domain user based on uid */ -wbcErr wbcGetgrgid(gid_t gid, struct group **grp) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (!grp) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - request.data.gid = gid; - - wbc_status = wbcRequestResponse(WINBINDD_GETGRGID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - *grp = copy_group_entry(&response.data.gr, - (char*)response.extra_data.data); - BAIL_ON_PTR_ERROR(*grp, wbc_status); - - done: - if (response.extra_data.data) - free(response.extra_data.data); - - return wbc_status; -} - -/** @brief Number of cached passwd structs - * - */ -static uint32_t pw_cache_size; - -/** @brief Position of the pwent context - * - */ -static uint32_t pw_cache_idx; - -/** @brief Winbindd response containing the passwd structs - * - */ -static struct winbindd_response pw_response; - -/* Reset the passwd iterator */ -wbcErr wbcSetpwent(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (pw_cache_size > 0) { - pw_cache_idx = pw_cache_size = 0; - if (pw_response.extra_data.data) { - free(pw_response.extra_data.data); - } - } - - ZERO_STRUCT(pw_response); - - wbc_status = wbcRequestResponse(WINBINDD_SETPWENT, - NULL, NULL); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Close the passwd iterator */ -wbcErr wbcEndpwent(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (pw_cache_size > 0) { - pw_cache_idx = pw_cache_size = 0; - if (pw_response.extra_data.data) { - free(pw_response.extra_data.data); - } - } - - wbc_status = wbcRequestResponse(WINBINDD_ENDPWENT, - NULL, NULL); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Return the next struct passwd* entry from the pwent iterator */ -wbcErr wbcGetpwent(struct passwd **pwd) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_pw *wb_pw; - - /* If there's a cached result, return that. */ - if (pw_cache_idx < pw_cache_size) { - goto return_result; - } - - /* Otherwise, query winbindd for some entries. */ - - pw_cache_idx = 0; - - if (pw_response.extra_data.data) { - free(pw_response.extra_data.data); - ZERO_STRUCT(pw_response); - } - - ZERO_STRUCT(request); - request.data.num_entries = MAX_GETPWENT_USERS; - - wbc_status = wbcRequestResponse(WINBINDD_GETPWENT, &request, - &pw_response); - - BAIL_ON_WBC_ERROR(wbc_status); - - pw_cache_size = pw_response.data.num_entries; - -return_result: - - wb_pw = (struct winbindd_pw *) pw_response.extra_data.data; - - *pwd = copy_passwd_entry(&wb_pw[pw_cache_idx]); - - BAIL_ON_PTR_ERROR(*pwd, wbc_status); - - pw_cache_idx++; - -done: - return wbc_status; -} - -/** @brief Number of cached group structs - * - */ -static uint32_t gr_cache_size; - -/** @brief Position of the grent context - * - */ -static uint32_t gr_cache_idx; - -/** @brief Winbindd response containing the group structs - * - */ -static struct winbindd_response gr_response; - -/* Reset the group iterator */ -wbcErr wbcSetgrent(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (gr_cache_size > 0) { - gr_cache_idx = gr_cache_size = 0; - if (gr_response.extra_data.data) { - free(gr_response.extra_data.data); - } - } - - ZERO_STRUCT(gr_response); - - wbc_status = wbcRequestResponse(WINBINDD_SETGRENT, - NULL, NULL); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Close the group iterator */ -wbcErr wbcEndgrent(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (gr_cache_size > 0) { - gr_cache_idx = gr_cache_size = 0; - if (gr_response.extra_data.data) { - free(gr_response.extra_data.data); - } - } - - wbc_status = wbcRequestResponse(WINBINDD_ENDGRENT, - NULL, NULL); - BAIL_ON_WBC_ERROR(wbc_status); - - done: - return wbc_status; -} - -/* Return the next struct group* entry from the pwent iterator */ -wbcErr wbcGetgrent(struct group **grp) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_gr *wb_gr; - uint32_t mem_ofs; - - /* If there's a cached result, return that. */ - if (gr_cache_idx < gr_cache_size) { - goto return_result; - } - - /* Otherwise, query winbindd for some entries. */ - - gr_cache_idx = 0; - - if (gr_response.extra_data.data) { - free(gr_response.extra_data.data); - ZERO_STRUCT(gr_response); - } - - ZERO_STRUCT(request); - request.data.num_entries = MAX_GETGRENT_GROUPS; - - wbc_status = wbcRequestResponse(WINBINDD_GETGRENT, &request, - &gr_response); - - BAIL_ON_WBC_ERROR(wbc_status); - - gr_cache_size = gr_response.data.num_entries; - -return_result: - - wb_gr = (struct winbindd_gr *) gr_response.extra_data.data; - - mem_ofs = wb_gr[gr_cache_idx].gr_mem_ofs + - gr_cache_size * sizeof(struct winbindd_gr); - - *grp = copy_group_entry(&wb_gr[gr_cache_idx], - ((char *)gr_response.extra_data.data)+mem_ofs); - - BAIL_ON_PTR_ERROR(*grp, wbc_status); - - gr_cache_idx++; - -done: - return wbc_status; -} - -/* Return the next struct group* entry from the pwent iterator */ -wbcErr wbcGetgrlist(struct group **grp) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_gr *wb_gr; - - /* If there's a cached result, return that. */ - if (gr_cache_idx < gr_cache_size) { - goto return_result; - } - - /* Otherwise, query winbindd for some entries. */ - - gr_cache_idx = 0; - - if (gr_response.extra_data.data) { - free(gr_response.extra_data.data); - ZERO_STRUCT(gr_response); - } - - ZERO_STRUCT(request); - request.data.num_entries = MAX_GETGRENT_GROUPS; - - wbc_status = wbcRequestResponse(WINBINDD_GETGRLST, &request, - &gr_response); - - BAIL_ON_WBC_ERROR(wbc_status); - - gr_cache_size = gr_response.data.num_entries; - -return_result: - - wb_gr = (struct winbindd_gr *) gr_response.extra_data.data; - - *grp = copy_group_entry(&wb_gr[gr_cache_idx], NULL); - - BAIL_ON_PTR_ERROR(*grp, wbc_status); - - gr_cache_idx++; - -done: - return wbc_status; -} - -/* Return the unix group array belonging to the given user */ -wbcErr wbcGetGroups(const char *account, - uint32_t *num_groups, - gid_t **_groups) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - uint32_t i; - gid_t *groups = NULL; - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (!account) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Send request */ - - strncpy(request.data.username, account, sizeof(request.data.username)-1); - - wbc_status = wbcRequestResponse(WINBINDD_GETGROUPS, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - groups = talloc_array(NULL, gid_t, response.data.num_entries); - BAIL_ON_PTR_ERROR(groups, wbc_status); - - for (i = 0; i < response.data.num_entries; i++) { - groups[i] = ((gid_t *)response.extra_data.data)[i]; - } - - *num_groups = response.data.num_entries; - *_groups = groups; - groups = NULL; - - wbc_status = WBC_ERR_SUCCESS; - - done: - if (response.extra_data.data) { - free(response.extra_data.data); - } - if (groups) { - talloc_free(groups); - } - - return wbc_status; -} diff --git a/source3/nsswitch/libwbclient/wbc_sid.c b/source3/nsswitch/libwbclient/wbc_sid.c deleted file mode 100644 index e2157b9609..0000000000 --- a/source3/nsswitch/libwbclient/wbc_sid.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - - -/* Convert a binary SID to a character string */ -wbcErr wbcSidToString(const struct wbcDomainSid *sid, - char **sid_string) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uint32_t id_auth; - int i; - char *tmp = NULL; - - if (!sid) { - wbc_status = WBC_ERR_INVALID_SID; - BAIL_ON_WBC_ERROR(wbc_status); - } - - id_auth = sid->id_auth[5] + - (sid->id_auth[4] << 8) + - (sid->id_auth[3] << 16) + - (sid->id_auth[2] << 24); - - tmp = talloc_asprintf(NULL, "S-%d-%d", sid->sid_rev_num, id_auth); - BAIL_ON_PTR_ERROR(tmp, wbc_status); - - for (i=0; inum_auths; i++) { - char *tmp2; - tmp2 = talloc_asprintf_append(tmp, "-%u", sid->sub_auths[i]); - BAIL_ON_PTR_ERROR(tmp2, wbc_status); - - tmp = tmp2; - } - - *sid_string = tmp; - tmp = NULL; - - wbc_status = WBC_ERR_SUCCESS; - -done: - talloc_free(tmp); - - return wbc_status; -} - -/* Convert a character string to a binary SID */ -wbcErr wbcStringToSid(const char *str, - struct wbcDomainSid *sid) -{ - const char *p; - char *q; - uint32_t x; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!sid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Sanity check for either "S-" or "s-" */ - - if (!str - || (str[0]!='S' && str[0]!='s') - || (str[1]!='-')) - { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Get the SID revision number */ - - p = str+2; - x = (uint32_t)strtol(p, &q, 10); - if (x==0 || !q || *q!='-') { - wbc_status = WBC_ERR_INVALID_SID; - BAIL_ON_WBC_ERROR(wbc_status); - } - sid->sid_rev_num = (uint8_t)x; - - /* Next the Identifier Authority. This is stored in big-endian - in a 6 byte array. */ - - p = q+1; - x = (uint32_t)strtol(p, &q, 10); - if (!q || *q!='-') { - wbc_status = WBC_ERR_INVALID_SID; - BAIL_ON_WBC_ERROR(wbc_status); - } - sid->id_auth[5] = (x & 0x000000ff); - sid->id_auth[4] = (x & 0x0000ff00) >> 8; - sid->id_auth[3] = (x & 0x00ff0000) >> 16; - sid->id_auth[2] = (x & 0xff000000) >> 24; - sid->id_auth[1] = 0; - sid->id_auth[0] = 0; - - /* now read the the subauthorities */ - - p = q +1; - sid->num_auths = 0; - while (sid->num_auths < WBC_MAXSUBAUTHS) { - x=(uint32_t)strtoul(p, &q, 10); - if (p == q) - break; - if (q == NULL) { - wbc_status = WBC_ERR_INVALID_SID; - BAIL_ON_WBC_ERROR(wbc_status); - } - sid->sub_auths[sid->num_auths++] = x; - - if ((*q!='-') || (*q=='\0')) - break; - p = q + 1; - } - - /* IF we ended early, then the SID could not be converted */ - - if (q && *q!='\0') { - wbc_status = WBC_ERR_INVALID_SID; - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = WBC_ERR_SUCCESS; - -done: - return wbc_status; - -} - -/* Convert a domain and name to SID */ -wbcErr wbcLookupName(const char *domain, - const char *name, - struct wbcDomainSid *sid, - enum wbcSidType *name_type) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - if (!sid || !name_type) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* dst is already null terminated from the memset above */ - - strncpy(request.data.name.dom_name, domain, - sizeof(request.data.name.dom_name)-1); - strncpy(request.data.name.name, name, - sizeof(request.data.name.name)-1); - - wbc_status = wbcRequestResponse(WINBINDD_LOOKUPNAME, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - wbc_status = wbcStringToSid(response.data.sid.sid, sid); - BAIL_ON_WBC_ERROR(wbc_status); - - *name_type = (enum wbcSidType)response.data.sid.type; - - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* Convert a SID to a domain and name */ -wbcErr wbcLookupSid(const struct wbcDomainSid *sid, - char **pdomain, - char **pname, - enum wbcSidType *pname_type) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *sid_string = NULL; - char *domain = NULL; - char *name = NULL; - enum wbcSidType name_type = WBC_SID_NAME_USE_NONE; - - if (!sid) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* dst is already null terminated from the memset above */ - - wbc_status = wbcSidToString(sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); - wbcFreeMemory(sid_string); - - /* Make request */ - - wbc_status = wbcRequestResponse(WINBINDD_LOOKUPSID, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Copy out result */ - - domain = talloc_strdup(NULL, response.data.name.dom_name); - BAIL_ON_PTR_ERROR(domain, wbc_status); - - name = talloc_strdup(NULL, response.data.name.name); - BAIL_ON_PTR_ERROR(name, wbc_status); - - name_type = (enum wbcSidType)response.data.name.type; - - wbc_status = WBC_ERR_SUCCESS; - - done: - if (WBC_ERROR_IS_OK(wbc_status)) { - if (pdomain != NULL) { - *pdomain = domain; - } - if (pname != NULL) { - *pname = name; - } - if (pname_type != NULL) { - *pname_type = name_type; - } - } - else { -#if 0 - /* - * Found by Coverity: In this particular routine we can't end - * up here with a non-NULL name. Further up there are just two - * exit paths that lead here, neither of which leave an - * allocated name. If you add more paths up there, re-activate - * this. - */ - if (name != NULL) { - talloc_free(name); - } -#endif - if (domain != NULL) { - talloc_free(domain); - } - } - - return wbc_status; -} - -/* Translate a collection of RIDs within a domain to names */ - -wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid, - int num_rids, - uint32_t *rids, - const char **pp_domain_name, - const char ***pnames, - enum wbcSidType **ptypes) -{ - size_t i, len, ridbuf_size; - char *ridlist; - char *p; - struct winbindd_request request; - struct winbindd_response response; - char *sid_string = NULL; - char *domain_name = NULL; - const char **names = NULL; - enum wbcSidType *types = NULL; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - - /* Initialise request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (!dom_sid || (num_rids == 0)) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = wbcSidToString(dom_sid, &sid_string); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.sid, sid_string, sizeof(request.data.sid)-1); - wbcFreeMemory(sid_string); - - /* Even if all the Rids were of maximum 32bit values, - we would only have 11 bytes per rid in the final array - ("4294967296" + \n). Add one more byte for the - terminating '\0' */ - - ridbuf_size = (sizeof(char)*11) * num_rids + 1; - - ridlist = talloc_zero_array(NULL, char, ridbuf_size); - BAIL_ON_PTR_ERROR(ridlist, wbc_status); - - len = 0; - for (i=0; i0; i++) { - char ridstr[12]; - - len = strlen(ridlist); - p = ridlist + len; - - snprintf( ridstr, sizeof(ridstr)-1, "%u\n", rids[i]); - strncat(p, ridstr, ridbuf_size-len-1); - } - - request.extra_data.data = ridlist; - request.extra_len = strlen(ridlist)+1; - - wbc_status = wbcRequestResponse(WINBINDD_LOOKUPRIDS, - &request, - &response); - talloc_free(ridlist); - BAIL_ON_WBC_ERROR(wbc_status); - - domain_name = talloc_strdup(NULL, response.data.domain_name); - BAIL_ON_PTR_ERROR(domain_name, wbc_status); - - names = talloc_array(NULL, const char*, num_rids); - BAIL_ON_PTR_ERROR(names, wbc_status); - - types = talloc_array(NULL, enum wbcSidType, num_rids); - BAIL_ON_PTR_ERROR(types, wbc_status); - - p = (char *)response.extra_data.data; - - for (i=0; ipw_gecos); - BAIL_ON_PTR_ERROR(name, wbc_status); - } - - wbc_status = WBC_ERR_SUCCESS; - - done: - if (WBC_ERROR_IS_OK(wbc_status)) { - *pdomain = domain; - *pfullname = name; - *pname_type = name_type; - } else { - wbcFreeMemory(domain); - wbcFreeMemory(name); - } - - return wbc_status; -} diff --git a/source3/nsswitch/libwbclient/wbc_util.c b/source3/nsswitch/libwbclient/wbc_util.c deleted file mode 100644 index 7cfb64b87e..0000000000 --- a/source3/nsswitch/libwbclient/wbc_util.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007-2008 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - - - -/** @brief Ping winbindd to see if the daemon is running - * - * @return #wbcErr - **/ - -wbcErr wbcPing(void) -{ - struct winbindd_request request; - struct winbindd_response response; - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - return wbcRequestResponse(WINBINDD_PING, &request, &response); -} - -wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **_details) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcInterfaceDetails *info; - struct wbcDomainInfo *domain = NULL; - struct winbindd_request request; - struct winbindd_response response; - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - info = talloc(NULL, struct wbcInterfaceDetails); - BAIL_ON_PTR_ERROR(info, wbc_status); - - /* first the interface version */ - wbc_status = wbcRequestResponse(WINBINDD_INTERFACE_VERSION, NULL, &response); - BAIL_ON_WBC_ERROR(wbc_status); - info->interface_version = response.data.interface_version; - - /* then the samba version and the winbind separator */ - wbc_status = wbcRequestResponse(WINBINDD_INFO, NULL, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - info->winbind_version = talloc_strdup(info, - response.data.info.samba_version); - BAIL_ON_PTR_ERROR(info->winbind_version, wbc_status); - info->winbind_separator = response.data.info.winbind_separator; - - /* then the local netbios name */ - wbc_status = wbcRequestResponse(WINBINDD_NETBIOS_NAME, NULL, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - info->netbios_name = talloc_strdup(info, - response.data.netbios_name); - BAIL_ON_PTR_ERROR(info->netbios_name, wbc_status); - - /* then the local workgroup name */ - wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_NAME, NULL, &response); - BAIL_ON_WBC_ERROR(wbc_status); - - info->netbios_domain = talloc_strdup(info, - response.data.domain_name); - BAIL_ON_PTR_ERROR(info->netbios_domain, wbc_status); - - wbc_status = wbcDomainInfo(info->netbios_domain, &domain); - if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) { - /* maybe it's a standalone server */ - domain = NULL; - wbc_status = WBC_ERR_SUCCESS; - } else { - BAIL_ON_WBC_ERROR(wbc_status); - } - - if (domain) { - info->dns_domain = talloc_strdup(info, - domain->dns_name); - wbcFreeMemory(domain); - BAIL_ON_PTR_ERROR(info->dns_domain, wbc_status); - } else { - info->dns_domain = NULL; - } - - *_details = info; - info = NULL; - - wbc_status = WBC_ERR_SUCCESS; - -done: - talloc_free(info); - return wbc_status; -} - - -/* Lookup the current status of a trusted domain */ -wbcErr wbcDomainInfo(const char *domain, struct wbcDomainInfo **dinfo) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainInfo *info = NULL; - - if (!domain || !dinfo) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Initialize request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.domain_name, domain, - sizeof(request.domain_name)-1); - - wbc_status = wbcRequestResponse(WINBINDD_DOMAIN_INFO, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - info = talloc(NULL, struct wbcDomainInfo); - BAIL_ON_PTR_ERROR(info, wbc_status); - - info->short_name = talloc_strdup(info, - response.data.domain_info.name); - BAIL_ON_PTR_ERROR(info->short_name, wbc_status); - - info->dns_name = talloc_strdup(info, - response.data.domain_info.alt_name); - BAIL_ON_PTR_ERROR(info->dns_name, wbc_status); - - wbc_status = wbcStringToSid(response.data.domain_info.sid, - &info->sid); - BAIL_ON_WBC_ERROR(wbc_status); - - if (response.data.domain_info.native_mode) - info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE; - if (response.data.domain_info.active_directory) - info->domain_flags |= WBC_DOMINFO_DOMAIN_AD; - if (response.data.domain_info.primary) - info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY; - - *dinfo = info; - - wbc_status = WBC_ERR_SUCCESS; - - done: - if (!WBC_ERROR_IS_OK(wbc_status)) { - talloc_free(info); - } - - return wbc_status; -} - - -/* Resolve a NetbiosName via WINS */ -wbcErr wbcResolveWinsByName(const char *name, char **ip) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *ipaddr; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - strncpy(request.data.winsreq, name, - sizeof(request.data.winsreq)-1); - - wbc_status = wbcRequestResponse(WINBINDD_WINS_BYNAME, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Display response */ - - ipaddr = talloc_strdup(NULL, response.data.winsresp); - BAIL_ON_PTR_ERROR(ipaddr, wbc_status); - - *ip = ipaddr; - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* Resolve an IP address via WINS into a NetbiosName */ -wbcErr wbcResolveWinsByIP(const char *ip, char **name) -{ - struct winbindd_request request; - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *name_str; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - strncpy(request.data.winsreq, ip, - sizeof(request.data.winsreq)-1); - - wbc_status = wbcRequestResponse(WINBINDD_WINS_BYIP, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Display response */ - - name_str = talloc_strdup(NULL, response.data.winsresp); - BAIL_ON_PTR_ERROR(name_str, wbc_status); - - *name = name_str; - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/** - */ - -static wbcErr process_domain_info_string(TALLOC_CTX *ctx, - struct wbcDomainInfo *info, - char *info_string) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *r = NULL; - char *s = NULL; - - if (!info || !info_string) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - r = info_string; - - /* Short Name */ - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - info->short_name = talloc_strdup(ctx, r); - BAIL_ON_PTR_ERROR(info->short_name, wbc_status); - - - /* DNS Name */ - r = s; - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - info->dns_name = talloc_strdup(ctx, r); - BAIL_ON_PTR_ERROR(info->dns_name, wbc_status); - - /* SID */ - r = s; - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - wbc_status = wbcStringToSid(r, &info->sid); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Trust type */ - r = s; - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - if (strcmp(r, "None") == 0) { - info->trust_type = WBC_DOMINFO_TRUSTTYPE_NONE; - } else if (strcmp(r, "External") == 0) { - info->trust_type = WBC_DOMINFO_TRUSTTYPE_EXTERNAL; - } else if (strcmp(r, "Forest") == 0) { - info->trust_type = WBC_DOMINFO_TRUSTTYPE_FOREST; - } else if (strcmp(r, "In Forest") == 0) { - info->trust_type = WBC_DOMINFO_TRUSTTYPE_IN_FOREST; - } else { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Transitive */ - r = s; - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - if (strcmp(r, "Yes") == 0) { - info->trust_flags |= WBC_DOMINFO_TRUST_TRANSITIVE; - } - - /* Incoming */ - r = s; - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - if (strcmp(r, "Yes") == 0) { - info->trust_flags |= WBC_DOMINFO_TRUST_INCOMING; - } - - /* Outgoing */ - r = s; - if ((s = strchr(r, '\\')) == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - *s = '\0'; - s++; - - if (strcmp(r, "Yes") == 0) { - info->trust_flags |= WBC_DOMINFO_TRUST_OUTGOING; - } - - /* Online/Offline status */ - - r = s; - if (r == NULL) { - wbc_status = WBC_ERR_INVALID_RESPONSE; - BAIL_ON_WBC_ERROR(wbc_status); - } - if ( strcmp(r, "Offline") == 0) { - info->domain_flags |= WBC_DOMINFO_DOMAIN_OFFLINE; - } - - wbc_status = WBC_ERR_SUCCESS; - - done: - return wbc_status; -} - -/* Enumerate the domain trusts known by Winbind */ -wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains) -{ - struct winbindd_response response; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *p = NULL; - char *q = NULL; - char *extra_data = NULL; - int count = 0; - struct wbcDomainInfo *d_list = NULL; - int i = 0; - - *domains = NULL; - *num_domains = 0; - - ZERO_STRUCT(response); - - /* Send request */ - - wbc_status = wbcRequestResponse(WINBINDD_LIST_TRUSTDOM, - NULL, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - /* Decode the response */ - - p = (char *)response.extra_data.data; - - if (strlen(p) == 0) { - /* We should always at least get back our - own SAM domain */ - - wbc_status = WBC_ERR_DOMAIN_NOT_FOUND; - BAIL_ON_WBC_ERROR(wbc_status); - } - - /* Count number of domains */ - - count = 0; - while (p) { - count++; - - if ((q = strchr(p, '\n')) != NULL) - q++; - p = q; - } - - d_list = talloc_array(NULL, struct wbcDomainInfo, count); - BAIL_ON_PTR_ERROR(d_list, wbc_status); - - extra_data = strdup((char*)response.extra_data.data); - BAIL_ON_PTR_ERROR(extra_data, wbc_status); - - p = extra_data; - - /* Outer loop processes the list of domain information */ - - for (i=0; idc_name = talloc_strdup(dc, response.data.dc_name); - BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status); - - *dc_info = dc; - -done: - if (!WBC_ERROR_IS_OK(wbc_status)) { - talloc_free(dc); - } - - return wbc_status; -} - -static wbcErr wbc_create_domain_controller_info_ex(TALLOC_CTX *mem_ctx, - const struct winbindd_response *resp, - struct wbcDomainControllerInfoEx **_i) -{ - wbcErr wbc_status = WBC_ERR_SUCCESS; - struct wbcDomainControllerInfoEx *i; - struct wbcGuid guid; - - i = talloc(mem_ctx, struct wbcDomainControllerInfoEx); - BAIL_ON_PTR_ERROR(i, wbc_status); - - i->dc_unc = talloc_strdup(i, resp->data.dsgetdcname.dc_unc); - BAIL_ON_PTR_ERROR(i->dc_unc, wbc_status); - - i->dc_address = talloc_strdup(i, resp->data.dsgetdcname.dc_address); - BAIL_ON_PTR_ERROR(i->dc_address, wbc_status); - - i->dc_address_type = resp->data.dsgetdcname.dc_address_type; - - wbc_status = wbcStringToGuid(resp->data.dsgetdcname.domain_guid, &guid); - if (WBC_ERROR_IS_OK(wbc_status)) { - i->domain_guid = talloc(i, struct wbcGuid); - BAIL_ON_PTR_ERROR(i->domain_guid, wbc_status); - - *i->domain_guid = guid; - } else { - i->domain_guid = NULL; - } - - i->domain_name = talloc_strdup(i, resp->data.dsgetdcname.domain_name); - BAIL_ON_PTR_ERROR(i->domain_name, wbc_status); - - if (resp->data.dsgetdcname.forest_name[0] != '\0') { - i->forest_name = talloc_strdup(i, - resp->data.dsgetdcname.forest_name); - BAIL_ON_PTR_ERROR(i->forest_name, wbc_status); - } else { - i->forest_name = NULL; - } - - i->dc_flags = resp->data.dsgetdcname.dc_flags; - - if (resp->data.dsgetdcname.dc_site_name[0] != '\0') { - i->dc_site_name = talloc_strdup(i, - resp->data.dsgetdcname.dc_site_name); - BAIL_ON_PTR_ERROR(i->dc_site_name, wbc_status); - } else { - i->dc_site_name = NULL; - } - - if (resp->data.dsgetdcname.client_site_name[0] != '\0') { - i->client_site_name = talloc_strdup(i, - resp->data.dsgetdcname.client_site_name); - BAIL_ON_PTR_ERROR(i->client_site_name, wbc_status); - } else { - i->client_site_name = NULL; - } - - *_i = i; - i = NULL; - -done: - talloc_free(i); - return wbc_status; -} - -/* Get extended domain controller information */ -wbcErr wbcLookupDomainControllerEx(const char *domain, - struct wbcGuid *guid, - const char *site, - uint32_t flags, - struct wbcDomainControllerInfoEx **dc_info) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct winbindd_request request; - struct winbindd_response response; - - /* validate input params */ - - if (!domain || !dc_info) { - wbc_status = WBC_ERR_INVALID_PARAM; - BAIL_ON_WBC_ERROR(wbc_status); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.dsgetdcname.flags = flags; - - strncpy(request.data.dsgetdcname.domain_name, domain, - sizeof(request.data.dsgetdcname.domain_name)-1); - - if (site) { - strncpy(request.data.dsgetdcname.site_name, site, - sizeof(request.data.dsgetdcname.site_name)-1); - } - - if (guid) { - char *str = NULL; - - wbc_status = wbcGuidToString(guid, &str); - BAIL_ON_WBC_ERROR(wbc_status); - - strncpy(request.data.dsgetdcname.domain_guid, str, - sizeof(request.data.dsgetdcname.domain_guid)-1); - - wbcFreeMemory(str); - } - - /* Send request */ - - wbc_status = wbcRequestResponse(WINBINDD_DSGETDCNAME, - &request, - &response); - BAIL_ON_WBC_ERROR(wbc_status); - - if (dc_info) { - wbc_status = wbc_create_domain_controller_info_ex(NULL, - &response, - dc_info); - BAIL_ON_WBC_ERROR(wbc_status); - } - - wbc_status = WBC_ERR_SUCCESS; -done: - return wbc_status; -} - -/* Initialize a named blob and add to list of blobs */ -wbcErr wbcAddNamedBlob(size_t *num_blobs, - struct wbcNamedBlob **blobs, - const char *name, - uint32_t flags, - uint8_t *data, - size_t length) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcNamedBlob blob; - - *blobs = talloc_realloc(NULL, *blobs, struct wbcNamedBlob, - *(num_blobs)+1); - BAIL_ON_PTR_ERROR(*blobs, wbc_status); - - blob.name = talloc_strdup(*blobs, name); - BAIL_ON_PTR_ERROR(blob.name, wbc_status); - blob.flags = flags; - blob.blob.length = length; - blob.blob.data = (uint8_t *)talloc_memdup(*blobs, data, length); - BAIL_ON_PTR_ERROR(blob.blob.data, wbc_status); - - (*(blobs))[*num_blobs] = blob; - *(num_blobs) += 1; - - wbc_status = WBC_ERR_SUCCESS; -done: - if (!WBC_ERROR_IS_OK(wbc_status) && blobs) { - wbcFreeMemory(*blobs); - } - return wbc_status; -} diff --git a/source3/nsswitch/libwbclient/wbclient.c b/source3/nsswitch/libwbclient/wbclient.c deleted file mode 100644 index 3a9afad15d..0000000000 --- a/source3/nsswitch/libwbclient/wbclient.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* Required Headers */ - -#include "libwbclient.h" - -/* From wb_common.c */ - -NSS_STATUS winbindd_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); - -/** @brief Wrapper around Winbind's send/receive API call - * - * @param cmd Winbind command operation to perform - * @param request Send structure - * @param response Receive structure - * - * @return #wbcErr - **/ - -/********************************************************************** - result == NSS_STATUS_UNAVAIL: winbind not around - result == NSS_STATUS_NOTFOUND: winbind around, but domain missing - - Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off - and when winbind return WINBINDD_ERROR. So the semantics of this - routine depends on winbind_on. Grepping for winbind_off I just - found 3 places where winbind is turned off, and this does not conflict - (as far as I have seen) with the callers of is_trusted_domains. - - --Volker -**********************************************************************/ - -wbcErr wbcRequestResponse(int cmd, - struct winbindd_request *request, - struct winbindd_response *response) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - NSS_STATUS nss_status; - - /* for some calls the request and/or response can be NULL */ - - nss_status = winbindd_request_response(cmd, request, response); - - switch (nss_status) { - case NSS_STATUS_SUCCESS: - wbc_status = WBC_ERR_SUCCESS; - break; - case NSS_STATUS_UNAVAIL: - wbc_status = WBC_ERR_WINBIND_NOT_AVAILABLE; - break; - case NSS_STATUS_NOTFOUND: - wbc_status = WBC_ERR_DOMAIN_NOT_FOUND; - break; - default: - wbc_status = WBC_ERR_NSS_ERROR; - break; - } - - return wbc_status; -} - -/** @brief Translate an error value into a string - * - * @param error - * - * @return a pointer to a static string - **/ -const char *wbcErrorString(wbcErr error) -{ - switch (error) { - case WBC_ERR_SUCCESS: - return "WBC_ERR_SUCCESS"; - case WBC_ERR_NOT_IMPLEMENTED: - return "WBC_ERR_NOT_IMPLEMENTED"; - case WBC_ERR_UNKNOWN_FAILURE: - return "WBC_ERR_UNKNOWN_FAILURE"; - case WBC_ERR_NO_MEMORY: - return "WBC_ERR_NO_MEMORY"; - case WBC_ERR_INVALID_SID: - return "WBC_ERR_INVALID_SID"; - case WBC_ERR_INVALID_PARAM: - return "WBC_ERR_INVALID_PARAM"; - case WBC_ERR_WINBIND_NOT_AVAILABLE: - return "WBC_ERR_WINBIND_NOT_AVAILABLE"; - case WBC_ERR_DOMAIN_NOT_FOUND: - return "WBC_ERR_DOMAIN_NOT_FOUND"; - case WBC_ERR_INVALID_RESPONSE: - return "WBC_ERR_INVALID_RESPONSE"; - case WBC_ERR_NSS_ERROR: - return "WBC_ERR_NSS_ERROR"; - case WBC_ERR_UNKNOWN_USER: - return "WBC_ERR_UNKNOWN_USER"; - case WBC_ERR_UNKNOWN_GROUP: - return "WBC_ERR_UNKNOWN_GROUP"; - case WBC_ERR_AUTH_ERROR: - return "WBC_ERR_AUTH_ERROR"; - case WBC_ERR_PWD_CHANGE_FAILED: - return "WBC_ERR_PWD_CHANGE_FAILED"; - } - - return "unknown wbcErr value"; -} - -/* Free library allocated memory */ -void wbcFreeMemory(void *p) -{ - if (p) - talloc_free(p); - - return; -} - -wbcErr wbcLibraryDetails(struct wbcLibraryDetails **_details) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcLibraryDetails *info; - - info = talloc(NULL, struct wbcLibraryDetails); - BAIL_ON_PTR_ERROR(info, wbc_status); - - info->major_version = WBCLIENT_MAJOR_VERSION; - info->minor_version = WBCLIENT_MINOR_VERSION; - info->vendor_version = talloc_strdup(info, - WBCLIENT_VENDOR_VERSION); - BAIL_ON_PTR_ERROR(info->vendor_version, wbc_status); - - *_details = info; - info = NULL; - - wbc_status = WBC_ERR_SUCCESS; - -done: - talloc_free(info); - return wbc_status; -} - - diff --git a/source3/nsswitch/libwbclient/wbclient.h b/source3/nsswitch/libwbclient/wbclient.h deleted file mode 100644 index fcad3ff69b..0000000000 --- a/source3/nsswitch/libwbclient/wbclient.h +++ /dev/null @@ -1,1187 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WBCLIENT_H -#define _WBCLIENT_H - -#include -#include - -/* Define error types */ - -/** - * @brief Status codes returned from wbc functions - **/ - -enum _wbcErrType { - WBC_ERR_SUCCESS = 0, /**< Successful completion **/ - WBC_ERR_NOT_IMPLEMENTED,/**< Function not implemented **/ - WBC_ERR_UNKNOWN_FAILURE,/**< General failure **/ - WBC_ERR_NO_MEMORY, /**< Memory allocation error **/ - WBC_ERR_INVALID_SID, /**< Invalid SID format **/ - WBC_ERR_INVALID_PARAM, /**< An Invalid parameter was supplied **/ - WBC_ERR_WINBIND_NOT_AVAILABLE, /**< Winbind daemon is not available **/ - WBC_ERR_DOMAIN_NOT_FOUND, /**< Domain is not trusted or cannot be found **/ - WBC_ERR_INVALID_RESPONSE, /**< Winbind returned an invalid response **/ - WBC_ERR_NSS_ERROR, /**< NSS_STATUS error **/ - WBC_ERR_AUTH_ERROR, /**< Authentication failed **/ - WBC_ERR_UNKNOWN_USER, /**< User account cannot be found */ - WBC_ERR_UNKNOWN_GROUP, /**< Group account cannot be found */ - WBC_ERR_PWD_CHANGE_FAILED /**< Password Change has failed */ -}; - -typedef enum _wbcErrType wbcErr; - -#define WBC_ERROR_IS_OK(x) ((x) == WBC_ERR_SUCCESS) - -const char *wbcErrorString(wbcErr error); - -/** - * @brief Some useful details about the wbclient library - * - * 0.1: Initial version - * 0.2: Added wbcRemoveUidMapping() - * Added wbcRemoveGidMapping() - **/ -#define WBCLIENT_MAJOR_VERSION 0 -#define WBCLIENT_MINOR_VERSION 2 -#define WBCLIENT_VENDOR_VERSION "Samba libwbclient" -struct wbcLibraryDetails { - uint16_t major_version; - uint16_t minor_version; - const char *vendor_version; -}; - -/** - * @brief Some useful details about the running winbindd - * - **/ -struct wbcInterfaceDetails { - uint32_t interface_version; - const char *winbind_version; - char winbind_separator; - const char *netbios_name; - const char *netbios_domain; - const char *dns_domain; -}; - -/* - * Data types used by the Winbind Client API - */ - -#ifndef WBC_MAXSUBAUTHS -#define WBC_MAXSUBAUTHS 15 /* max sub authorities in a SID */ -#endif - -/** - * @brief Windows Security Identifier - * - **/ - -struct wbcDomainSid { - uint8_t sid_rev_num; - uint8_t num_auths; - uint8_t id_auth[6]; - uint32_t sub_auths[WBC_MAXSUBAUTHS]; -}; - -/** - * @brief Security Identifier type - **/ - -enum wbcSidType { - WBC_SID_NAME_USE_NONE=0, - WBC_SID_NAME_USER=1, - WBC_SID_NAME_DOM_GRP=2, - WBC_SID_NAME_DOMAIN=3, - WBC_SID_NAME_ALIAS=4, - WBC_SID_NAME_WKN_GRP=5, - WBC_SID_NAME_DELETED=6, - WBC_SID_NAME_INVALID=7, - WBC_SID_NAME_UNKNOWN=8, - WBC_SID_NAME_COMPUTER=9 -}; - -/** - * @brief Security Identifier with attributes - **/ - -struct wbcSidWithAttr { - struct wbcDomainSid sid; - uint32_t attributes; -}; - -/* wbcSidWithAttr->attributes */ - -#define WBC_SID_ATTR_GROUP_MANDATORY 0x00000001 -#define WBC_SID_ATTR_GROUP_ENABLED_BY_DEFAULT 0x00000002 -#define WBC_SID_ATTR_GROUP_ENABLED 0x00000004 -#define WBC_SID_ATTR_GROUP_OWNER 0x00000008 -#define WBC_SID_ATTR_GROUP_USEFOR_DENY_ONLY 0x00000010 -#define WBC_SID_ATTR_GROUP_RESOURCE 0x20000000 -#define WBC_SID_ATTR_GROUP_LOGON_ID 0xC0000000 - -/** - * @brief Windows GUID - * - **/ - -struct wbcGuid { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq[2]; - uint8_t node[6]; -}; - -/** - * @brief Domain Information - **/ - -struct wbcDomainInfo { - char *short_name; - char *dns_name; - struct wbcDomainSid sid; - uint32_t domain_flags; - uint32_t trust_flags; - uint32_t trust_type; -}; - -/* wbcDomainInfo->domain_flags */ - -#define WBC_DOMINFO_DOMAIN_UNKNOWN 0x00000000 -#define WBC_DOMINFO_DOMAIN_NATIVE 0x00000001 -#define WBC_DOMINFO_DOMAIN_AD 0x00000002 -#define WBC_DOMINFO_DOMAIN_PRIMARY 0x00000004 -#define WBC_DOMINFO_DOMAIN_OFFLINE 0x00000008 - -/* wbcDomainInfo->trust_flags */ - -#define WBC_DOMINFO_TRUST_TRANSITIVE 0x00000001 -#define WBC_DOMINFO_TRUST_INCOMING 0x00000002 -#define WBC_DOMINFO_TRUST_OUTGOING 0x00000004 - -/* wbcDomainInfo->trust_type */ - -#define WBC_DOMINFO_TRUSTTYPE_NONE 0x00000000 -#define WBC_DOMINFO_TRUSTTYPE_FOREST 0x00000001 -#define WBC_DOMINFO_TRUSTTYPE_IN_FOREST 0x00000002 -#define WBC_DOMINFO_TRUSTTYPE_EXTERNAL 0x00000003 - - -/** - * @brief Auth User Parameters - **/ - -struct wbcAuthUserParams { - const char *account_name; - const char *domain_name; - const char *workstation_name; - - uint32_t flags; - - uint32_t parameter_control; - - enum wbcAuthUserLevel { - WBC_AUTH_USER_LEVEL_PLAIN = 1, - WBC_AUTH_USER_LEVEL_HASH = 2, - WBC_AUTH_USER_LEVEL_RESPONSE = 3 - } level; - union { - const char *plaintext; - struct { - uint8_t nt_hash[16]; - uint8_t lm_hash[16]; - } hash; - struct { - uint8_t challenge[8]; - uint32_t nt_length; - uint8_t *nt_data; - uint32_t lm_length; - uint8_t *lm_data; - } response; - } password; -}; - -/** - * @brief Generic Blob - **/ - -struct wbcBlob { - uint8_t *data; - size_t length; -}; - -/** - * @brief Named Blob - **/ - -struct wbcNamedBlob { - const char *name; - uint32_t flags; - struct wbcBlob blob; -}; - -/** - * @brief Logon User Parameters - **/ - -struct wbcLogonUserParams { - const char *username; - const char *password; - size_t num_blobs; - struct wbcNamedBlob *blobs; -}; - -/** - * @brief ChangePassword Parameters - **/ - -struct wbcChangePasswordParams { - const char *account_name; - const char *domain_name; - - uint32_t flags; - - enum wbcChangePasswordLevel { - WBC_CHANGE_PASSWORD_LEVEL_PLAIN = 1, - WBC_CHANGE_PASSWORD_LEVEL_RESPONSE = 2 - } level; - - union { - const char *plaintext; - struct { - uint32_t old_nt_hash_enc_length; - uint8_t *old_nt_hash_enc_data; - uint32_t old_lm_hash_enc_length; - uint8_t *old_lm_hash_enc_data; - } response; - } old_password; - union { - const char *plaintext; - struct { - uint32_t nt_length; - uint8_t *nt_data; - uint32_t lm_length; - uint8_t *lm_data; - } response; - } new_password; -}; - -/* wbcAuthUserParams->parameter_control */ - -#define WBC_MSV1_0_CLEARTEXT_PASSWORD_ALLOWED 0x00000002 -#define WBC_MSV1_0_UPDATE_LOGON_STATISTICS 0x00000004 -#define WBC_MSV1_0_RETURN_USER_PARAMETERS 0x00000008 -#define WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT 0x00000020 -#define WBC_MSV1_0_RETURN_PROFILE_PATH 0x00000200 -#define WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT 0x00000800 - -/* wbcAuthUserParams->flags */ - -#define WBC_AUTH_PARAM_FLAGS_INTERACTIVE_LOGON 0x00000001 - -/** - * @brief Auth User Information - * - * Some of the strings are maybe NULL - **/ - -struct wbcAuthUserInfo { - uint32_t user_flags; - - char *account_name; - char *user_principal; - char *full_name; - char *domain_name; - char *dns_domain_name; - - uint32_t acct_flags; - uint8_t user_session_key[16]; - uint8_t lm_session_key[8]; - - uint16_t logon_count; - uint16_t bad_password_count; - - uint64_t logon_time; - uint64_t logoff_time; - uint64_t kickoff_time; - uint64_t pass_last_set_time; - uint64_t pass_can_change_time; - uint64_t pass_must_change_time; - - char *logon_server; - char *logon_script; - char *profile_path; - char *home_directory; - char *home_drive; - - /* - * the 1st one is the account sid - * the 2nd one is the primary_group sid - * followed by the rest of the groups - */ - uint32_t num_sids; - struct wbcSidWithAttr *sids; -}; - -/** - * @brief Logon User Information - * - * Some of the strings are maybe NULL - **/ - -struct wbcLogonUserInfo { - struct wbcAuthUserInfo *info; - size_t num_blobs; - struct wbcNamedBlob *blobs; -}; - -/* wbcAuthUserInfo->user_flags */ - -#define WBC_AUTH_USER_INFO_GUEST 0x00000001 -#define WBC_AUTH_USER_INFO_NOENCRYPTION 0x00000002 -#define WBC_AUTH_USER_INFO_CACHED_ACCOUNT 0x00000004 -#define WBC_AUTH_USER_INFO_USED_LM_PASSWORD 0x00000008 -#define WBC_AUTH_USER_INFO_EXTRA_SIDS 0x00000020 -#define WBC_AUTH_USER_INFO_SUBAUTH_SESSION_KEY 0x00000040 -#define WBC_AUTH_USER_INFO_SERVER_TRUST_ACCOUNT 0x00000080 -#define WBC_AUTH_USER_INFO_NTLMV2_ENABLED 0x00000100 -#define WBC_AUTH_USER_INFO_RESOURCE_GROUPS 0x00000200 -#define WBC_AUTH_USER_INFO_PROFILE_PATH_RETURNED 0x00000400 -#define WBC_AUTH_USER_INFO_GRACE_LOGON 0x01000000 - -/* wbcAuthUserInfo->acct_flags */ - -#define WBC_ACB_DISABLED 0x00000001 /* 1 User account disabled */ -#define WBC_ACB_HOMDIRREQ 0x00000002 /* 1 Home directory required */ -#define WBC_ACB_PWNOTREQ 0x00000004 /* 1 User password not required */ -#define WBC_ACB_TEMPDUP 0x00000008 /* 1 Temporary duplicate account */ -#define WBC_ACB_NORMAL 0x00000010 /* 1 Normal user account */ -#define WBC_ACB_MNS 0x00000020 /* 1 MNS logon user account */ -#define WBC_ACB_DOMTRUST 0x00000040 /* 1 Interdomain trust account */ -#define WBC_ACB_WSTRUST 0x00000080 /* 1 Workstation trust account */ -#define WBC_ACB_SVRTRUST 0x00000100 /* 1 Server trust account */ -#define WBC_ACB_PWNOEXP 0x00000200 /* 1 User password does not expire */ -#define WBC_ACB_AUTOLOCK 0x00000400 /* 1 Account auto locked */ -#define WBC_ACB_ENC_TXT_PWD_ALLOWED 0x00000800 /* 1 Encryped text password is allowed */ -#define WBC_ACB_SMARTCARD_REQUIRED 0x00001000 /* 1 Smart Card required */ -#define WBC_ACB_TRUSTED_FOR_DELEGATION 0x00002000 /* 1 Trusted for Delegation */ -#define WBC_ACB_NOT_DELEGATED 0x00004000 /* 1 Not delegated */ -#define WBC_ACB_USE_DES_KEY_ONLY 0x00008000 /* 1 Use DES key only */ -#define WBC_ACB_DONT_REQUIRE_PREAUTH 0x00010000 /* 1 Preauth not required */ -#define WBC_ACB_PW_EXPIRED 0x00020000 /* 1 Password Expired */ -#define WBC_ACB_NO_AUTH_DATA_REQD 0x00080000 /* 1 = No authorization data required */ - -struct wbcAuthErrorInfo { - uint32_t nt_status; - char *nt_string; - int32_t pam_error; - char *display_string; -}; - -/** - * @brief User Password Policy Information - **/ - -/* wbcUserPasswordPolicyInfo->password_properties */ - -#define WBC_DOMAIN_PASSWORD_COMPLEX 0x00000001 -#define WBC_DOMAIN_PASSWORD_NO_ANON_CHANGE 0x00000002 -#define WBC_DOMAIN_PASSWORD_NO_CLEAR_CHANGE 0x00000004 -#define WBC_DOMAIN_PASSWORD_LOCKOUT_ADMINS 0x00000008 -#define WBC_DOMAIN_PASSWORD_STORE_CLEARTEXT 0x00000010 -#define WBC_DOMAIN_REFUSE_PASSWORD_CHANGE 0x00000020 - -struct wbcUserPasswordPolicyInfo { - uint32_t min_length_password; - uint32_t password_history; - uint32_t password_properties; - uint64_t expire; - uint64_t min_passwordage; -}; - -/** - * @brief Change Password Reject Reason - **/ - -enum wbcPasswordChangeRejectReason { - WBC_PWD_CHANGE_REJECT_OTHER=0, - WBC_PWD_CHANGE_REJECT_TOO_SHORT=1, - WBC_PWD_CHANGE_REJECT_IN_HISTORY=2, - WBC_PWD_CHANGE_REJECT_COMPLEXITY=5 -}; - -/** - * @brief Logoff User Parameters - **/ - -struct wbcLogoffUserParams { - const char *username; - size_t num_blobs; - struct wbcNamedBlob *blobs; -}; - -/** @brief Credential cache log-on parameters - * - */ - -struct wbcCredentialCacheParams { - const char *account_name; - const char *domain_name; - enum wbcCredentialCacheLevel { - WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP = 1 - } level; - size_t num_blobs; - struct wbcNamedBlob *blobs; -}; - - -/** @brief Info returned by credential cache auth - * - */ - -struct wbcCredentialCacheInfo { - size_t num_blobs; - struct wbcNamedBlob *blobs; -}; - -/* - * DomainControllerInfo struct - */ -struct wbcDomainControllerInfo { - char *dc_name; -}; - -/* - * DomainControllerInfoEx struct - */ -struct wbcDomainControllerInfoEx { - const char *dc_unc; - const char *dc_address; - uint16_t dc_address_type; - struct wbcGuid *domain_guid; - const char *domain_name; - const char *forest_name; - uint32_t dc_flags; - const char *dc_site_name; - const char *client_site_name; -}; - -/********************************************************** - * Memory Management - **********************************************************/ - -/** - * @brief Free library allocated memory - * - * @param *p Pointer to free - * - * @return void - **/ -void wbcFreeMemory(void*); - - -/* - * Utility functions for dealing with SIDs - */ - -/** - * @brief Convert a binary SID to a character string - * - * @param sid Binary Security Identifier - * @param **sid_string Resulting character string - * - * @return #wbcErr - **/ -wbcErr wbcSidToString(const struct wbcDomainSid *sid, - char **sid_string); - -/** - * @brief Convert a character string to a binary SID - * - * @param *str Character string in the form of S-... - * @param sid Resulting binary SID - * - * @return #wbcErr - **/ -wbcErr wbcStringToSid(const char *sid_string, - struct wbcDomainSid *sid); - -/* - * Utility functions for dealing with GUIDs - */ - -/** - * @brief Convert a binary GUID to a character string - * - * @param guid Binary Guid - * @param **guid_string Resulting character string - * - * @return #wbcErr - **/ -wbcErr wbcGuidToString(const struct wbcGuid *guid, - char **guid_string); - -/** - * @brief Convert a character string to a binary GUID - * - * @param *str Character string - * @param guid Resulting binary GUID - * - * @return #wbcErr - **/ -wbcErr wbcStringToGuid(const char *guid_string, - struct wbcGuid *guid); - -/** - * @brief Ping winbindd to see if the daemon is running - * - * @return #wbcErr - **/ -wbcErr wbcPing(void); - -wbcErr wbcLibraryDetails(struct wbcLibraryDetails **details); - -wbcErr wbcInterfaceDetails(struct wbcInterfaceDetails **details); - -/********************************************************** - * Name/SID conversion - **********************************************************/ - -/** - * @brief Convert a domain and name to SID - * - * @param domain Domain name (possibly "") - * @param name User or group name - * @param *sid Pointer to the resolved domain SID - * @param *name_type Pointer to the SID type - * - * @return #wbcErr - **/ -wbcErr wbcLookupName(const char *dom_name, - const char *name, - struct wbcDomainSid *sid, - enum wbcSidType *name_type); - -/** - * @brief Convert a SID to a domain and name - * - * @param *sid Pointer to the domain SID to be resolved - * @param pdomain Resolved Domain name (possibly "") - * @param pname Resolved User or group name - * @param *pname_type Pointer to the resolved SID type - * - * @return #wbcErr - **/ -wbcErr wbcLookupSid(const struct wbcDomainSid *sid, - char **domain, - char **name, - enum wbcSidType *name_type); - -/** - * @brief Translate a collection of RIDs within a domain to names - */ -wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid, - int num_rids, - uint32_t *rids, - const char **domain_name, - const char ***names, - enum wbcSidType **types); - -/* - * @brief Get the groups a user belongs to - **/ -wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid, - bool domain_groups_only, - uint32_t *num_sids, - struct wbcDomainSid **sids); - -/** - * @brief Lists Users - **/ -wbcErr wbcListUsers(const char *domain_name, - uint32_t *num_users, - const char ***users); - -/** - * @brief Lists Groups - **/ -wbcErr wbcListGroups(const char *domain_name, - uint32_t *num_groups, - const char ***groups); - -wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid, - char **pdomain, - char **pfullname, - enum wbcSidType *pname_type); - -/********************************************************** - * SID/uid/gid Mappings - **********************************************************/ - -/** - * @brief Convert a Windows SID to a Unix uid, allocating an uid if needed - * - * @param *sid Pointer to the domain SID to be resolved - * @param *puid Pointer to the resolved uid_t value - * - * @return #wbcErr - * - **/ -wbcErr wbcSidToUid(const struct wbcDomainSid *sid, - uid_t *puid); - -/** - * @brief Convert a Windows SID to a Unix uid if there already is a mapping - * - * @param *sid Pointer to the domain SID to be resolved - * @param *puid Pointer to the resolved uid_t value - * - * @return #wbcErr - * - **/ -wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid, - uid_t *puid); - -/** - * @brief Convert a Unix uid to a Windows SID, allocating a SID if needed - * - * @param uid Unix uid to be resolved - * @param *sid Pointer to the resolved domain SID - * - * @return #wbcErr - * - **/ -wbcErr wbcUidToSid(uid_t uid, - struct wbcDomainSid *sid); - -/** - * @brief Convert a Unix uid to a Windows SID if there already is a mapping - * - * @param uid Unix uid to be resolved - * @param *sid Pointer to the resolved domain SID - * - * @return #wbcErr - * - **/ -wbcErr wbcQueryUidToSid(uid_t uid, - struct wbcDomainSid *sid); - -/** - * @brief Convert a Windows SID to a Unix gid, allocating a gid if needed - * - * @param *sid Pointer to the domain SID to be resolved - * @param *pgid Pointer to the resolved gid_t value - * - * @return #wbcErr - * - **/ -wbcErr wbcSidToGid(const struct wbcDomainSid *sid, - gid_t *pgid); - -/** - * @brief Convert a Windows SID to a Unix gid if there already is a mapping - * - * @param *sid Pointer to the domain SID to be resolved - * @param *pgid Pointer to the resolved gid_t value - * - * @return #wbcErr - * - **/ -wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid, - gid_t *pgid); - -/** - * @brief Convert a Unix gid to a Windows SID, allocating a SID if needed - * - * @param gid Unix gid to be resolved - * @param *sid Pointer to the resolved domain SID - * - * @return #wbcErr - * - **/ -wbcErr wbcGidToSid(gid_t gid, - struct wbcDomainSid *sid); - -/** - * @brief Convert a Unix gid to a Windows SID if there already is a mapping - * - * @param gid Unix gid to be resolved - * @param *sid Pointer to the resolved domain SID - * - * @return #wbcErr - * - **/ -wbcErr wbcQueryGidToSid(gid_t gid, - struct wbcDomainSid *sid); - -/** - * @brief Obtain a new uid from Winbind - * - * @param *puid *pointer to the allocated uid - * - * @return #wbcErr - **/ -wbcErr wbcAllocateUid(uid_t *puid); - -/** - * @brief Obtain a new gid from Winbind - * - * @param *pgid Pointer to the allocated gid - * - * @return #wbcErr - **/ -wbcErr wbcAllocateGid(gid_t *pgid); - -/** - * @brief Set an user id mapping - * - * @param uid Uid of the desired mapping. - * @param *sid Pointer to the sid of the diresired mapping. - * - * @return #wbcErr - **/ -wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid); - -/** - * @brief Set a group id mapping - * - * @param gid Gid of the desired mapping. - * @param *sid Pointer to the sid of the diresired mapping. - * - * @return #wbcErr - **/ -wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid); - -/** - * @brief Remove a user id mapping - * - * @param uid Uid of the mapping to remove. - * @param *sid Pointer to the sid of the mapping to remove. - * - * @return #wbcErr - **/ -wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid); - -/** - * @brief Remove a group id mapping - * - * @param gid Gid of the mapping to remove. - * @param *sid Pointer to the sid of the mapping to remove. - * - * @return #wbcErr - **/ -wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid); - -/** - * @brief Set the highwater mark for allocated uids. - * - * @param uid_hwm The new uid highwater mark value - * - * @return #wbcErr - **/ -wbcErr wbcSetUidHwm(uid_t uid_hwm); - -/** - * @brief Set the highwater mark for allocated gids. - * - * @param gid_hwm The new gid highwater mark value - * - * @return #wbcErr - **/ -wbcErr wbcSetGidHwm(gid_t gid_hwm); - -/********************************************************** - * NSS Lookup User/Group details - **********************************************************/ - -/** - * @brief Fill in a struct passwd* for a domain user based - * on username - * - * @param *name Username to lookup - * @param **pwd Pointer to resulting struct passwd* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetpwnam(const char *name, struct passwd **pwd); - -/** - * @brief Fill in a struct passwd* for a domain user based - * on uid - * - * @param uid Uid to lookup - * @param **pwd Pointer to resulting struct passwd* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetpwuid(uid_t uid, struct passwd **pwd); - -/** - * @brief Fill in a struct passwd* for a domain user based - * on username - * - * @param *name Username to lookup - * @param **grp Pointer to resulting struct group* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetgrnam(const char *name, struct group **grp); - -/** - * @brief Fill in a struct passwd* for a domain user based - * on uid - * - * @param gid Uid to lookup - * @param **grp Pointer to resulting struct group* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetgrgid(gid_t gid, struct group **grp); - -/** - * @brief Reset the passwd iterator - * - * @return #wbcErr - **/ -wbcErr wbcSetpwent(void); - -/** - * @brief Close the passwd iterator - * - * @return #wbcErr - **/ -wbcErr wbcEndpwent(void); - -/** - * @brief Return the next struct passwd* entry from the pwent iterator - * - * @param **pwd Pointer to resulting struct passwd* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetpwent(struct passwd **pwd); - -/** - * @brief Reset the group iterator - * - * @return #wbcErr - **/ -wbcErr wbcSetgrent(void); - -/** - * @brief Close the group iterator - * - * @return #wbcErr - **/ -wbcErr wbcEndgrent(void); - -/** - * @brief Return the next struct group* entry from the pwent iterator - * - * @param **grp Pointer to resulting struct group* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetgrent(struct group **grp); - -/** - * @brief Return the next struct group* entry from the pwent iterator - * - * This is similar to #wbcGetgrent, just that the member list is empty - * - * @param **grp Pointer to resulting struct group* from the query. - * - * @return #wbcErr - **/ -wbcErr wbcGetgrlist(struct group **grp); - -/** - * @brief Return the unix group array belonging to the given user - * - * @param *account The given user name - * @param *num_groups Number of elements returned in the groups array - * @param **_groups Pointer to resulting gid_t array. - * - * @return #wbcErr - **/ -wbcErr wbcGetGroups(const char *account, - uint32_t *num_groups, - gid_t **_groups); - - -/********************************************************** - * Lookup Domain information - **********************************************************/ - -/** - * @brief Lookup the current status of a trusted domain - * - * @param domain Domain to query - * @param *dinfo Pointer to returned domain_info struct - * - * @return #wbcErr - **/ -wbcErr wbcDomainInfo(const char *domain, - struct wbcDomainInfo **info); - -/** - * @brief Enumerate the domain trusts known by Winbind - * - * @param **domains Pointer to the allocated domain list array - * @param *num_domains Pointer to number of domains returned - * - * @return #wbcErr - **/ -wbcErr wbcListTrusts(struct wbcDomainInfo **domains, - size_t *num_domains); - -/* Flags for wbcLookupDomainController */ - -#define WBC_LOOKUP_DC_FORCE_REDISCOVERY 0x00000001 -#define WBC_LOOKUP_DC_DS_REQUIRED 0x00000010 -#define WBC_LOOKUP_DC_DS_PREFERRED 0x00000020 -#define WBC_LOOKUP_DC_GC_SERVER_REQUIRED 0x00000040 -#define WBC_LOOKUP_DC_PDC_REQUIRED 0x00000080 -#define WBC_LOOKUP_DC_BACKGROUND_ONLY 0x00000100 -#define WBC_LOOKUP_DC_IP_REQUIRED 0x00000200 -#define WBC_LOOKUP_DC_KDC_REQUIRED 0x00000400 -#define WBC_LOOKUP_DC_TIMESERV_REQUIRED 0x00000800 -#define WBC_LOOKUP_DC_WRITABLE_REQUIRED 0x00001000 -#define WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED 0x00002000 -#define WBC_LOOKUP_DC_AVOID_SELF 0x00004000 -#define WBC_LOOKUP_DC_ONLY_LDAP_NEEDED 0x00008000 -#define WBC_LOOKUP_DC_IS_FLAT_NAME 0x00010000 -#define WBC_LOOKUP_DC_IS_DNS_NAME 0x00020000 -#define WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE 0x00040000 -#define WBC_LOOKUP_DC_DS_6_REQUIRED 0x00080000 -#define WBC_LOOKUP_DC_RETURN_DNS_NAME 0x40000000 -#define WBC_LOOKUP_DC_RETURN_FLAT_NAME 0x80000000 - -/** - * @brief Enumerate the domain trusts known by Winbind - * - * @param domain Name of the domain to query for a DC - * @param flags Bit flags used to control the domain location query - * @param *dc_info Pointer to the returned domain controller information - * - * @return #wbcErr - **/ -wbcErr wbcLookupDomainController(const char *domain, - uint32_t flags, - struct wbcDomainControllerInfo **dc_info); - -/** - * @brief Get extended domain controller information - * - * @param domain Name of the domain to query for a DC - * @param guid Guid of the domain to query for a DC - * @param site Site of the domain to query for a DC - * @param flags Bit flags used to control the domain location query - * @param *dc_info Pointer to the returned extended domain controller information - * - * @return #wbcErr - **/ -wbcErr wbcLookupDomainControllerEx(const char *domain, - struct wbcGuid *guid, - const char *site, - uint32_t flags, - struct wbcDomainControllerInfoEx **dc_info); - -/********************************************************** - * Athenticate functions - **********************************************************/ - -/** - * @brief Authenticate a username/password pair - * - * @param username Name of user to authenticate - * @param password Clear text password os user - * - * @return #wbcErr - **/ -wbcErr wbcAuthenticateUser(const char *username, - const char *password); - -/** - * @brief Authenticate with more detailed information - * - * @param params Input parameters, WBC_AUTH_USER_LEVEL_HASH - * is not supported yet - * @param info Output details on WBC_ERR_SUCCESS - * @param error Output details on WBC_ERR_AUTH_ERROR - * - * @return #wbcErr - **/ -wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params, - struct wbcAuthUserInfo **info, - struct wbcAuthErrorInfo **error); - -/** - * @brief Logon a User - * - * @param[in] params Pointer to a wbcLogonUserParams structure - * @param[out] info Pointer to a pointer to a wbcLogonUserInfo structure - * @param[out] error Pointer to a pointer to a wbcAuthErrorInfo structure - * @param[out] policy Pointer to a pointer to a wbcUserPasswordPolicyInfo structure - * - * @return #wbcErr - **/ -wbcErr wbcLogonUser(const struct wbcLogonUserParams *params, - struct wbcLogonUserInfo **info, - struct wbcAuthErrorInfo **error, - struct wbcUserPasswordPolicyInfo **policy); - -/** - * @brief Trigger a logoff notification to Winbind for a specific user - * - * @param username Name of user to remove from Winbind's list of - * logged on users. - * @param uid Uid assigned to the username - * @param ccfilename Absolute path to the Krb5 credentials cache to - * be removed - * - * @return #wbcErr - **/ -wbcErr wbcLogoffUser(const char *username, - uid_t uid, - const char *ccfilename); - -/** - * @brief Trigger an extended logoff notification to Winbind for a specific user - * - * @param params A wbcLogoffUserParams structure - * @param error User output details on error - * - * @return #wbcErr - **/ -wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params, - struct wbcAuthErrorInfo **error); - -/** - * @brief Change a password for a user - * - * @param username Name of user to authenticate - * @param old_password Old clear text password of user - * @param new_password New clear text password of user - * - * @return #wbcErr - **/ -wbcErr wbcChangeUserPassword(const char *username, - const char *old_password, - const char *new_password); - -/** - * @brief Change a password for a user with more detailed information upon - * failure - * - * @param params Input parameters - * @param error User output details on WBC_ERR_PWD_CHANGE_FAILED - * @param reject_reason New password reject reason on WBC_ERR_PWD_CHANGE_FAILED - * @param policy Password policy output details on WBC_ERR_PWD_CHANGE_FAILED - * - * @return #wbcErr - **/ -wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params, - struct wbcAuthErrorInfo **error, - enum wbcPasswordChangeRejectReason *reject_reason, - struct wbcUserPasswordPolicyInfo **policy); - -/** - * @brief Authenticate a user with cached credentials - * - * @param *params Pointer to a wbcCredentialCacheParams structure - * @param **info Pointer to a pointer to a wbcCredentialCacheInfo structure - * @param **error Pointer to a pointer to a wbcAuthErrorInfo structure - * - * @return #wbcErr - **/ -wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params, - struct wbcCredentialCacheInfo **info, - struct wbcAuthErrorInfo **error); - -/********************************************************** - * Resolve functions - **********************************************************/ - -/** - * @brief Resolve a NetbiosName via WINS - * - * @param name Name to resolve - * @param *ip Pointer to the ip address string - * - * @return #wbcErr - **/ -wbcErr wbcResolveWinsByName(const char *name, char **ip); - -/** - * @brief Resolve an IP address via WINS into a NetbiosName - * - * @param ip The ip address string - * @param *name Pointer to the name - * - * @return #wbcErr - * - **/ -wbcErr wbcResolveWinsByIP(const char *ip, char **name); - -/********************************************************** - * Trusted domain functions - **********************************************************/ - -/** - * @brief Trigger a verification of the trust credentials of a specific domain - * - * @param *domain The name of the domain, only NULL for the default domain is - * supported yet. Other values than NULL will result in - * WBC_ERR_NOT_IMPLEMENTED. - * @param error Output details on WBC_ERR_AUTH_ERROR - * - * @return #wbcErr - **/ -wbcErr wbcCheckTrustCredentials(const char *domain, - struct wbcAuthErrorInfo **error); - -/********************************************************** - * Helper functions - **********************************************************/ - -/** - * @brief Initialize a named blob and add to list of blobs - * - * @param[in,out] num_blobs Pointer to the number of blobs - * @param[in,out] blobs Pointer to an array of blobs - * @param[in] name Name of the new named blob - * @param[in] flags Flags of the new named blob - * @param[in] data Blob data of new blob - * @param[in] length Blob data length of new blob - * - * @return #wbcErr - **/ -wbcErr wbcAddNamedBlob(size_t *num_blobs, - struct wbcNamedBlob **blobs, - const char *name, - uint32_t flags, - uint8_t *data, - size_t length); - -#endif /* _WBCLIENT_H */ diff --git a/source3/nsswitch/libwbclient/wbclient_internal.h b/source3/nsswitch/libwbclient/wbclient_internal.h deleted file mode 100644 index fc03c5409b..0000000000 --- a/source3/nsswitch/libwbclient/wbclient_internal.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind client API - - Copyright (C) Gerald (Jerry) Carter 2007 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WBCLIENT_INTERNAL_H -#define _WBCLIENT_INTERNAL_H - -/* Private functions */ - -wbcErr wbcRequestResponse(int cmd, - struct winbindd_request *request, - struct winbindd_response *response); - - -#endif /* _WBCLIENT_INTERNAL_H */ diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c deleted file mode 100644 index d049bdb1e7..0000000000 --- a/source3/nsswitch/pam_winbind.c +++ /dev/null @@ -1,3204 +0,0 @@ -/* pam_winbind module - - Copyright Andrew Tridgell 2000 - Copyright Tim Potter 2000 - Copyright Andrew Bartlett 2002 - Copyright Guenther Deschner 2005-2008 - - largely based on pam_userdb by Cristian Gafton also - contains large slabs of code from pam_unix by Elliot Lee - (see copyright below for full details) -*/ - -#include "pam_winbind.h" - -static int wbc_error_to_pam_error(wbcErr status) -{ - switch (status) { - case WBC_ERR_SUCCESS: - return PAM_SUCCESS; - case WBC_ERR_NOT_IMPLEMENTED: - return PAM_SERVICE_ERR; - case WBC_ERR_UNKNOWN_FAILURE: - break; - case WBC_ERR_NO_MEMORY: - return PAM_BUF_ERR; - case WBC_ERR_INVALID_SID: - case WBC_ERR_INVALID_PARAM: - break; - case WBC_ERR_WINBIND_NOT_AVAILABLE: - return PAM_AUTHINFO_UNAVAIL; - case WBC_ERR_DOMAIN_NOT_FOUND: - return PAM_AUTHINFO_UNAVAIL; - case WBC_ERR_INVALID_RESPONSE: - return PAM_BUF_ERR; - case WBC_ERR_NSS_ERROR: - return PAM_USER_UNKNOWN; - case WBC_ERR_AUTH_ERROR: - return PAM_AUTH_ERR; - case WBC_ERR_UNKNOWN_USER: - return PAM_USER_UNKNOWN; - case WBC_ERR_UNKNOWN_GROUP: - return PAM_USER_UNKNOWN; - case WBC_ERR_PWD_CHANGE_FAILED: - break; - } - - /* be paranoid */ - return PAM_AUTH_ERR; -} - -static const char *_pam_error_code_str(int err) -{ - switch (err) { - case PAM_SUCCESS: - return "PAM_SUCCESS"; - case PAM_OPEN_ERR: - return "PAM_OPEN_ERR"; - case PAM_SYMBOL_ERR: - return "PAM_SYMBOL_ERR"; - case PAM_SERVICE_ERR: - return "PAM_SERVICE_ERR"; - case PAM_SYSTEM_ERR: - return "PAM_SYSTEM_ERR"; - case PAM_BUF_ERR: - return "PAM_BUF_ERR"; - case PAM_PERM_DENIED: - return "PAM_PERM_DENIED"; - case PAM_AUTH_ERR: - return "PAM_AUTH_ERR"; - case PAM_CRED_INSUFFICIENT: - return "PAM_CRED_INSUFFICIENT"; - case PAM_AUTHINFO_UNAVAIL: - return "PAM_AUTHINFO_UNAVAIL"; - case PAM_USER_UNKNOWN: - return "PAM_USER_UNKNOWN"; - case PAM_MAXTRIES: - return "PAM_MAXTRIES"; - case PAM_NEW_AUTHTOK_REQD: - return "PAM_NEW_AUTHTOK_REQD"; - case PAM_ACCT_EXPIRED: - return "PAM_ACCT_EXPIRED"; - case PAM_SESSION_ERR: - return "PAM_SESSION_ERR"; - case PAM_CRED_UNAVAIL: - return "PAM_CRED_UNAVAIL"; - case PAM_CRED_EXPIRED: - return "PAM_CRED_EXPIRED"; - case PAM_CRED_ERR: - return "PAM_CRED_ERR"; - case PAM_NO_MODULE_DATA: - return "PAM_NO_MODULE_DATA"; - case PAM_CONV_ERR: - return "PAM_CONV_ERR"; - case PAM_AUTHTOK_ERR: - return "PAM_AUTHTOK_ERR"; - case PAM_AUTHTOK_RECOVER_ERR: - return "PAM_AUTHTOK_RECOVER_ERR"; - case PAM_AUTHTOK_LOCK_BUSY: - return "PAM_AUTHTOK_LOCK_BUSY"; - case PAM_AUTHTOK_DISABLE_AGING: - return "PAM_AUTHTOK_DISABLE_AGING"; - case PAM_TRY_AGAIN: - return "PAM_TRY_AGAIN"; - case PAM_IGNORE: - return "PAM_IGNORE"; - case PAM_ABORT: - return "PAM_ABORT"; - case PAM_AUTHTOK_EXPIRED: - return "PAM_AUTHTOK_EXPIRED"; -#ifdef PAM_MODULE_UNKNOWN - case PAM_MODULE_UNKNOWN: - return "PAM_MODULE_UNKNOWN"; -#endif -#ifdef PAM_BAD_ITEM - case PAM_BAD_ITEM: - return "PAM_BAD_ITEM"; -#endif -#ifdef PAM_CONV_AGAIN - case PAM_CONV_AGAIN: - return "PAM_CONV_AGAIN"; -#endif -#ifdef PAM_INCOMPLETE - case PAM_INCOMPLETE: - return "PAM_INCOMPLETE"; -#endif - default: - return NULL; - } -} - -#define _PAM_LOG_FUNCTION_ENTER(function, ctx) \ - do { \ - _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] ENTER: " \ - function " (flags: 0x%04x)", ctx->pamh, ctx->flags); \ - _pam_log_state(ctx); \ - } while (0) - -#define _PAM_LOG_FUNCTION_LEAVE(function, ctx, retval) \ - do { \ - _pam_log_debug(ctx, LOG_DEBUG, "[pamh: %p] LEAVE: " \ - function " returning %d (%s)", ctx->pamh, retval, \ - _pam_error_code_str(retval)); \ - _pam_log_state(ctx); \ - } while (0) - -/* data tokens */ - -#define MAX_PASSWD_TRIES 3 - -#ifdef HAVE_GETTEXT -static char initialized = 0; - -static inline void textdomain_init(void); -static inline void textdomain_init(void) -{ - if (!initialized) { - bindtextdomain(MODULE_NAME, dyn_LOCALEDIR); - initialized = 1; - } - return; -} -#endif - - -/* - * Work around the pam API that has functions with void ** as parameters - * These lead to strict aliasing warnings with gcc. - */ -static int _pam_get_item(const pam_handle_t *pamh, - int item_type, - const void *_item) -{ - const void **item = (const void **)_item; - return pam_get_item(pamh, item_type, item); -} -static int _pam_get_data(const pam_handle_t *pamh, - const char *module_data_name, - const void *_data) -{ - const void **data = (const void **)_data; - return pam_get_data(pamh, module_data_name, data); -} - -/* some syslogging */ - -#ifdef HAVE_PAM_VSYSLOG -static void _pam_log_int(const pam_handle_t *pamh, - int err, - const char *format, - va_list args) -{ - pam_vsyslog(pamh, err, format, args); -} -#else -static void _pam_log_int(const pam_handle_t *pamh, - int err, - const char *format, - va_list args) -{ - char *format2 = NULL; - const char *service; - - _pam_get_item(pamh, PAM_SERVICE, &service); - - format2 = (char *)malloc(strlen(MODULE_NAME)+strlen(format)+strlen(service)+5); - if (format2 == NULL) { - /* what else todo ? */ - vsyslog(err, format, args); - return; - } - - sprintf(format2, "%s(%s): %s", MODULE_NAME, service, format); - vsyslog(err, format2, args); - SAFE_FREE(format2); -} -#endif /* HAVE_PAM_VSYSLOG */ - -static bool _pam_log_is_silent(int ctrl) -{ - return on(ctrl, WINBIND_SILENT); -} - -static void _pam_log(struct pwb_context *r, int err, const char *format, ...) PRINTF_ATTRIBUTE(3,4); -static void _pam_log(struct pwb_context *r, int err, const char *format, ...) -{ - va_list args; - - if (_pam_log_is_silent(r->ctrl)) { - return; - } - - va_start(args, format); - _pam_log_int(r->pamh, err, format, args); - va_end(args); -} -static void __pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); -static void __pam_log(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) -{ - va_list args; - - if (_pam_log_is_silent(ctrl)) { - return; - } - - va_start(args, format); - _pam_log_int(pamh, err, format, args); - va_end(args); -} - -static bool _pam_log_is_debug_enabled(int ctrl) -{ - if (ctrl == -1) { - return false; - } - - if (_pam_log_is_silent(ctrl)) { - return false; - } - - if (!(ctrl & WINBIND_DEBUG_ARG)) { - return false; - } - - return true; -} - -static bool _pam_log_is_debug_state_enabled(int ctrl) -{ - if (!(ctrl & WINBIND_DEBUG_STATE)) { - return false; - } - - return _pam_log_is_debug_enabled(ctrl); -} - -static void _pam_log_debug(struct pwb_context *r, int err, const char *format, ...) PRINTF_ATTRIBUTE(3,4); -static void _pam_log_debug(struct pwb_context *r, int err, const char *format, ...) -{ - va_list args; - - if (!_pam_log_is_debug_enabled(r->ctrl)) { - return; - } - - va_start(args, format); - _pam_log_int(r->pamh, err, format, args); - va_end(args); -} -static void __pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) PRINTF_ATTRIBUTE(4,5); -static void __pam_log_debug(const pam_handle_t *pamh, int ctrl, int err, const char *format, ...) -{ - va_list args; - - if (!_pam_log_is_debug_enabled(ctrl)) { - return; - } - - va_start(args, format); - _pam_log_int(pamh, err, format, args); - va_end(args); -} - -static void _pam_log_state_datum(struct pwb_context *ctx, - int item_type, - const char *key, - int is_string) -{ - const void *data = NULL; - if (item_type != 0) { - pam_get_item(ctx->pamh, item_type, &data); - } else { - pam_get_data(ctx->pamh, key, &data); - } - if (data != NULL) { - const char *type = (item_type != 0) ? "ITEM" : "DATA"; - if (is_string != 0) { - _pam_log_debug(ctx, LOG_DEBUG, - "[pamh: %p] STATE: %s(%s) = \"%s\" (%p)", - ctx->pamh, type, key, (const char *)data, - data); - } else { - _pam_log_debug(ctx, LOG_DEBUG, - "[pamh: %p] STATE: %s(%s) = %p", - ctx->pamh, type, key, data); - } - } -} - -#define _PAM_LOG_STATE_DATA_POINTER(ctx, module_data_name) \ - _pam_log_state_datum(ctx, 0, module_data_name, 0) - -#define _PAM_LOG_STATE_DATA_STRING(ctx, module_data_name) \ - _pam_log_state_datum(ctx, 0, module_data_name, 1) - -#define _PAM_LOG_STATE_ITEM_POINTER(ctx, item_type) \ - _pam_log_state_datum(ctx, item_type, #item_type, 0) - -#define _PAM_LOG_STATE_ITEM_STRING(ctx, item_type) \ - _pam_log_state_datum(ctx, item_type, #item_type, 1) - -#ifdef DEBUG_PASSWORD -#define _LOG_PASSWORD_AS_STRING 1 -#else -#define _LOG_PASSWORD_AS_STRING 0 -#endif - -#define _PAM_LOG_STATE_ITEM_PASSWORD(ctx, item_type) \ - _pam_log_state_datum(ctx, item_type, #item_type, \ - _LOG_PASSWORD_AS_STRING) - -static void _pam_log_state(struct pwb_context *ctx) -{ - if (!_pam_log_is_debug_state_enabled(ctx->ctrl)) { - return; - } - - _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_SERVICE); - _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_USER); - _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_TTY); - _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_RHOST); - _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_RUSER); - _PAM_LOG_STATE_ITEM_PASSWORD(ctx, PAM_OLDAUTHTOK); - _PAM_LOG_STATE_ITEM_PASSWORD(ctx, PAM_AUTHTOK); - _PAM_LOG_STATE_ITEM_STRING(ctx, PAM_USER_PROMPT); - _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_CONV); -#ifdef PAM_FAIL_DELAY - _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_FAIL_DELAY); -#endif -#ifdef PAM_REPOSITORY - _PAM_LOG_STATE_ITEM_POINTER(ctx, PAM_REPOSITORY); -#endif - - _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_HOMEDIR); - _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_LOGONSCRIPT); - _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_LOGONSERVER); - _PAM_LOG_STATE_DATA_STRING(ctx, PAM_WINBIND_PROFILEPATH); - _PAM_LOG_STATE_DATA_STRING(ctx, - PAM_WINBIND_NEW_AUTHTOK_REQD); - /* Use atoi to get PAM result code */ - _PAM_LOG_STATE_DATA_STRING(ctx, - PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH); - _PAM_LOG_STATE_DATA_POINTER(ctx, PAM_WINBIND_PWD_LAST_SET); -} - -static int _pam_parse(const pam_handle_t *pamh, - int flags, - int argc, - const char **argv, - dictionary **result_d) -{ - int ctrl = 0; - const char *config_file = NULL; - int i; - const char **v; - dictionary *d = NULL; - - if (flags & PAM_SILENT) { - ctrl |= WINBIND_SILENT; - } - - for (i=argc,v=argv; i-- > 0; ++v) { - if (!strncasecmp(*v, "config", strlen("config"))) { - ctrl |= WINBIND_CONFIG_FILE; - config_file = v[i]; - break; - } - } - - if (config_file == NULL) { - config_file = PAM_WINBIND_CONFIG_FILE; - } - - d = iniparser_load(config_file); - if (d == NULL) { - goto config_from_pam; - } - - if (iniparser_getboolean(d, "global:debug", false)) { - ctrl |= WINBIND_DEBUG_ARG; - } - - if (iniparser_getboolean(d, "global:debug_state", false)) { - ctrl |= WINBIND_DEBUG_STATE; - } - - if (iniparser_getboolean(d, "global:cached_login", false)) { - ctrl |= WINBIND_CACHED_LOGIN; - } - - if (iniparser_getboolean(d, "global:krb5_auth", false)) { - ctrl |= WINBIND_KRB5_AUTH; - } - - if (iniparser_getboolean(d, "global:silent", false)) { - ctrl |= WINBIND_SILENT; - } - - if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) { - ctrl |= WINBIND_KRB5_CCACHE_TYPE; - } - - if ((iniparser_getstr(d, "global:require-membership-of") != NULL) || - (iniparser_getstr(d, "global:require_membership_of") != NULL)) { - ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - } - - if (iniparser_getboolean(d, "global:try_first_pass", false)) { - ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - } - - if (iniparser_getint(d, "global:warn_pwd_expire", 0)) { - ctrl |= WINBIND_WARN_PWD_EXPIRE; - } - - if (iniparser_getboolean(d, "global:mkhomedir", false)) { - ctrl |= WINBIND_MKHOMEDIR; - } - -config_from_pam: - /* step through arguments */ - for (i=argc,v=argv; i-- > 0; ++v) { - - /* generic options */ - if (!strcmp(*v,"debug")) - ctrl |= WINBIND_DEBUG_ARG; - else if (!strcasecmp(*v, "debug_state")) - ctrl |= WINBIND_DEBUG_STATE; - else if (!strcasecmp(*v, "silent")) - ctrl |= WINBIND_SILENT; - else if (!strcasecmp(*v, "use_authtok")) - ctrl |= WINBIND_USE_AUTHTOK_ARG; - else if (!strcasecmp(*v, "use_first_pass")) - ctrl |= WINBIND_USE_FIRST_PASS_ARG; - else if (!strcasecmp(*v, "try_first_pass")) - ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (!strcasecmp(*v, "unknown_ok")) - ctrl |= WINBIND_UNKNOWN_OK_ARG; - else if (!strncasecmp(*v, "require_membership_of", - strlen("require_membership_of"))) - ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strncasecmp(*v, "require-membership-of", - strlen("require-membership-of"))) - ctrl |= WINBIND_REQUIRED_MEMBERSHIP; - else if (!strcasecmp(*v, "krb5_auth")) - ctrl |= WINBIND_KRB5_AUTH; - else if (!strncasecmp(*v, "krb5_ccache_type", - strlen("krb5_ccache_type"))) - ctrl |= WINBIND_KRB5_CCACHE_TYPE; - else if (!strcasecmp(*v, "cached_login")) - ctrl |= WINBIND_CACHED_LOGIN; - else if (!strcasecmp(*v, "mkhomedir")) - ctrl |= WINBIND_MKHOMEDIR; - else { - __pam_log(pamh, ctrl, LOG_ERR, - "pam_parse: unknown option: %s", *v); - return -1; - } - - } - - if (result_d) { - *result_d = d; - } else { - if (d) { - iniparser_freedict(d); - } - } - - return ctrl; -}; - -static int _pam_winbind_free_context(struct pwb_context *ctx) -{ - if (!ctx) { - return 0; - } - - if (ctx->dict) { - iniparser_freedict(ctx->dict); - } - - return 0; -} - -static int _pam_winbind_init_context(pam_handle_t *pamh, - int flags, - int argc, - const char **argv, - struct pwb_context **ctx_p) -{ - struct pwb_context *r = NULL; - -#ifdef HAVE_GETTEXT - textdomain_init(); -#endif - - r = TALLOC_ZERO_P(NULL, struct pwb_context); - if (!r) { - return PAM_BUF_ERR; - } - - talloc_set_destructor(r, _pam_winbind_free_context); - - r->pamh = pamh; - r->flags = flags; - r->argc = argc; - r->argv = argv; - r->ctrl = _pam_parse(pamh, flags, argc, argv, &r->dict); - if (r->ctrl == -1) { - TALLOC_FREE(r); - return PAM_SYSTEM_ERR; - } - - *ctx_p = r; - - return PAM_SUCCESS; -} - -static void _pam_winbind_cleanup_func(pam_handle_t *pamh, - void *data, - int error_status) -{ - int ctrl = _pam_parse(pamh, 0, 0, NULL, NULL); - if (_pam_log_is_debug_state_enabled(ctrl)) { - __pam_log_debug(pamh, ctrl, LOG_DEBUG, - "[pamh: %p] CLEAN: cleaning up PAM data %p " - "(error_status = %d)", pamh, data, - error_status); - } - TALLOC_FREE(data); -} - - -static const struct ntstatus_errors { - const char *ntstatus_string; - const char *error_string; -} ntstatus_errors[] = { - {"NT_STATUS_OK", - N_("Success")}, - {"NT_STATUS_BACKUP_CONTROLLER", - N_("No primary Domain Controler available")}, - {"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", - N_("No domain controllers found")}, - {"NT_STATUS_NO_LOGON_SERVERS", - N_("No logon servers")}, - {"NT_STATUS_PWD_TOO_SHORT", - N_("Password too short")}, - {"NT_STATUS_PWD_TOO_RECENT", - N_("The password of this user is too recent to change")}, - {"NT_STATUS_PWD_HISTORY_CONFLICT", - N_("Password is already in password history")}, - {"NT_STATUS_PASSWORD_EXPIRED", - N_("Your password has expired")}, - {"NT_STATUS_PASSWORD_MUST_CHANGE", - N_("You need to change your password now")}, - {"NT_STATUS_INVALID_WORKSTATION", - N_("You are not allowed to logon from this workstation")}, - {"NT_STATUS_INVALID_LOGON_HOURS", - N_("You are not allowed to logon at this time")}, - {"NT_STATUS_ACCOUNT_EXPIRED", - N_("Your account has expired. " - "Please contact your System administrator")}, /* SCNR */ - {"NT_STATUS_ACCOUNT_DISABLED", - N_("Your account is disabled. " - "Please contact your System administrator")}, /* SCNR */ - {"NT_STATUS_ACCOUNT_LOCKED_OUT", - N_("Your account has been locked. " - "Please contact your System administrator")}, /* SCNR */ - {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", - N_("Invalid Trust Account")}, - {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", - N_("Invalid Trust Account")}, - {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", - N_("Invalid Trust Account")}, - {"NT_STATUS_ACCESS_DENIED", - N_("Access is denied")}, - {NULL, NULL} -}; - -static const char *_get_ntstatus_error_string(const char *nt_status_string) -{ - int i; - for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) { - if (!strcasecmp(ntstatus_errors[i].ntstatus_string, - nt_status_string)) { - return _(ntstatus_errors[i].error_string); - } - } - return NULL; -} - -/* --- authentication management functions --- */ - -/* Attempt a conversation */ - -static int converse(const pam_handle_t *pamh, - int nargs, - struct pam_message **message, - struct pam_response **response) -{ - int retval; - struct pam_conv *conv; - - retval = _pam_get_item(pamh, PAM_CONV, &conv); - if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, - (const struct pam_message **)message, - response, conv->appdata_ptr); - } - - return retval; /* propagate error status */ -} - - -static int _make_remark(struct pwb_context *ctx, - int type, - const char *text) -{ - int retval = PAM_SUCCESS; - - struct pam_message *pmsg[1], msg[1]; - struct pam_response *resp; - - if (ctx->flags & WINBIND_SILENT) { - return PAM_SUCCESS; - } - - pmsg[0] = &msg[0]; - msg[0].msg = discard_const_p(char, text); - msg[0].msg_style = type; - - resp = NULL; - retval = converse(ctx->pamh, 1, pmsg, &resp); - - if (resp) { - _pam_drop_reply(resp, 1); - } - return retval; -} - -static int _make_remark_v(struct pwb_context *ctx, - int type, - const char *format, - va_list args) -{ - char *var; - int ret; - - ret = vasprintf(&var, format, args); - if (ret < 0) { - _pam_log(ctx, LOG_ERR, "memory allocation failure"); - return ret; - } - - ret = _make_remark(ctx, type, var); - SAFE_FREE(var); - return ret; -} - -static int _make_remark_format(struct pwb_context *ctx, int type, const char *format, ...) PRINTF_ATTRIBUTE(3,4); -static int _make_remark_format(struct pwb_context *ctx, int type, const char *format, ...) -{ - int ret; - va_list args; - - va_start(args, format); - ret = _make_remark_v(ctx, type, format, args); - va_end(args); - return ret; -} - -static int pam_winbind_request_log(struct pwb_context *ctx, - int retval, - const char *user, - const char *fn) -{ - switch (retval) { - case PAM_AUTH_ERR: - /* incorrect password */ - _pam_log(ctx, LOG_WARNING, "user '%s' denied access " - "(incorrect password or invalid membership)", user); - return retval; - case PAM_ACCT_EXPIRED: - /* account expired */ - _pam_log(ctx, LOG_WARNING, "user '%s' account expired", - user); - return retval; - case PAM_AUTHTOK_EXPIRED: - /* password expired */ - _pam_log(ctx, LOG_WARNING, "user '%s' password expired", - user); - return retval; - case PAM_NEW_AUTHTOK_REQD: - /* new password required */ - _pam_log(ctx, LOG_WARNING, "user '%s' new password " - "required", user); - return retval; - case PAM_USER_UNKNOWN: - /* the user does not exist */ - _pam_log_debug(ctx, LOG_NOTICE, "user '%s' not found", - user); - if (ctx->ctrl & WINBIND_UNKNOWN_OK_ARG) { - return PAM_IGNORE; - } - return retval; - case PAM_SUCCESS: - /* Otherwise, the authentication looked good */ - if (strcmp(fn, "wbcLogonUser") == 0) { - _pam_log(ctx, LOG_NOTICE, - "user '%s' granted access", user); - } else { - _pam_log(ctx, LOG_NOTICE, - "user '%s' OK", user); - } - return retval; - default: - /* we don't know anything about this return value */ - _pam_log(ctx, LOG_ERR, - "internal module error (retval = %s(%d), user = '%s')", - _pam_error_code_str(retval), retval, user); - return retval; - } -} - -static int wbc_auth_error_to_pam_error(struct pwb_context *ctx, - struct wbcAuthErrorInfo *e, - wbcErr status, - const char *username, - const char *fn) -{ - int ret = PAM_AUTH_ERR; - - if (WBC_ERROR_IS_OK(status)) { - _pam_log_debug(ctx, LOG_DEBUG, "request %s succeeded", - fn); - ret = PAM_SUCCESS; - return pam_winbind_request_log(ctx, ret, username, fn); - } - - if (e) { - if (e->pam_error != PAM_SUCCESS) { - _pam_log(ctx, LOG_ERR, - "request %s failed: %s, " - "PAM error: %s (%d), NTSTATUS: %s, " - "Error message was: %s", - fn, - wbcErrorString(status), - _pam_error_code_str(e->pam_error), - e->pam_error, - e->nt_string, - e->display_string); - ret = e->pam_error; - return pam_winbind_request_log(ctx, ret, username, fn); - } - - _pam_log(ctx, LOG_ERR, "request %s failed, but PAM error 0!", fn); - - ret = PAM_SERVICE_ERR; - return pam_winbind_request_log(ctx, ret, username, fn); - } - - ret = wbc_error_to_pam_error(status); - return pam_winbind_request_log(ctx, ret, username, fn); -} - - -/** - * send a password expiry message if required - * - * @param ctx PAM winbind context. - * @param next_change expected (calculated) next expiry date. - * @param already_expired pointer to a boolean to indicate if the password is - * already expired. - * - * @return boolean Returns true if message has been sent, false if not. - */ - -static bool _pam_send_password_expiry_message(struct pwb_context *ctx, - time_t next_change, - time_t now, - int warn_pwd_expire, - bool *already_expired) -{ - int days = 0; - struct tm tm_now, tm_next_change; - - if (already_expired) { - *already_expired = false; - } - - if (next_change <= now) { - PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PASSWORD_EXPIRED"); - if (already_expired) { - *already_expired = true; - } - return true; - } - - if ((next_change < 0) || - (next_change > now + warn_pwd_expire * SECONDS_PER_DAY)) { - return false; - } - - if ((localtime_r(&now, &tm_now) == NULL) || - (localtime_r(&next_change, &tm_next_change) == NULL)) { - return false; - } - - days = (tm_next_change.tm_yday+tm_next_change.tm_year*365) - - (tm_now.tm_yday+tm_now.tm_year*365); - - if (days == 0) { - _make_remark(ctx, PAM_TEXT_INFO, - _("Your password expires today")); - return true; - } - - if (days > 0 && days < warn_pwd_expire) { - _make_remark_format(ctx, PAM_TEXT_INFO, - _("Your password will expire in %d %s"), - days, (days > 1) ? _("days"):_("day")); - return true; - } - - return false; -} - -/** - * Send a warning if the password expires in the near future - * - * @param ctx PAM winbind context. - * @param response The full authentication response structure. - * @param already_expired boolean, is the pwd already expired? - * - * @return void. - */ - -static void _pam_warn_password_expiry(struct pwb_context *ctx, - const struct wbcAuthUserInfo *info, - const struct wbcUserPasswordPolicyInfo *policy, - int warn_pwd_expire, - bool *already_expired) -{ - time_t now = time(NULL); - time_t next_change = 0; - - if (!info || !policy) { - return; - } - - if (already_expired) { - *already_expired = false; - } - - /* accounts with WBC_ACB_PWNOEXP set never receive a warning */ - if (info->acct_flags & WBC_ACB_PWNOEXP) { - return; - } - - /* no point in sending a warning if this is a grace logon */ - if (PAM_WB_GRACE_LOGON(info->user_flags)) { - return; - } - - /* check if the info3 must change timestamp has been set */ - next_change = info->pass_must_change_time; - - if (_pam_send_password_expiry_message(ctx, next_change, now, - warn_pwd_expire, - already_expired)) { - return; - } - - /* now check for the global password policy */ - /* good catch from Ralf Haferkamp: an expiry of "never" is translated - * to -1 */ - if (policy->expire <= 0) { - return; - } - - next_change = info->pass_last_set_time + policy->expire; - - if (_pam_send_password_expiry_message(ctx, next_change, now, - warn_pwd_expire, - already_expired)) { - return; - } - - /* no warning sent */ -} - -#define IS_SID_STRING(name) (strncmp("S-", name, 2) == 0) - -/** - * Append a string, making sure not to overflow and to always return a - * NULL-terminated string. - * - * @param dest Destination string buffer (must already be NULL-terminated). - * @param src Source string buffer. - * @param dest_buffer_size Size of dest buffer in bytes. - * - * @return false if dest buffer is not big enough (no bytes copied), true on - * success. - */ - -static bool safe_append_string(char *dest, - const char *src, - int dest_buffer_size) -{ - int dest_length = strlen(dest); - int src_length = strlen(src); - - if (dest_length + src_length + 1 > dest_buffer_size) { - return false; - } - - memcpy(dest + dest_length, src, src_length + 1); - return true; -} - -/** - * Convert a names into a SID string, appending it to a buffer. - * - * @param ctx PAM winbind context. - * @param user User in PAM request. - * @param name Name to convert. - * @param sid_list_buffer Where to append the string sid. - * @param sid_list_buffer Size of sid_list_buffer (in bytes). - * - * @return false on failure, true on success. - */ -static bool winbind_name_to_sid_string(struct pwb_context *ctx, - const char *user, - const char *name, - char *sid_list_buffer, - int sid_list_buffer_size) -{ - const char* sid_string; - - /* lookup name? */ - if (IS_SID_STRING(name)) { - sid_string = name; - } else { - wbcErr wbc_status; - struct wbcDomainSid sid; - enum wbcSidType type; - char *sid_str; - - _pam_log_debug(ctx, LOG_DEBUG, - "no sid given, looking up: %s\n", name); - - wbc_status = wbcLookupName("", name, &sid, &type); - if (!WBC_ERROR_IS_OK(wbc_status)) { - _pam_log(ctx, LOG_INFO, - "could not lookup name: %s\n", name); - return false; - } - - wbc_status = wbcSidToString(&sid, &sid_str); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbcFreeMemory(sid_str); - sid_string = sid_str; - } - - if (!safe_append_string(sid_list_buffer, sid_string, - sid_list_buffer_size)) { - return false; - } - - return true; -} - -/** - * Convert a list of names into a list of sids. - * - * @param ctx PAM winbind context. - * @param user User in PAM request. - * @param name_list List of names or string sids, separated by commas. - * @param sid_list_buffer Where to put the list of string sids. - * @param sid_list_buffer Size of sid_list_buffer (in bytes). - * - * @return false on failure, true on success. - */ -static bool winbind_name_list_to_sid_string_list(struct pwb_context *ctx, - const char *user, - const char *name_list, - char *sid_list_buffer, - int sid_list_buffer_size) -{ - bool result = false; - char *current_name = NULL; - const char *search_location; - const char *comma; - - if (sid_list_buffer_size > 0) { - sid_list_buffer[0] = 0; - } - - search_location = name_list; - while ((comma = strstr(search_location, ",")) != NULL) { - current_name = strndup(search_location, - comma - search_location); - if (NULL == current_name) { - goto out; - } - - if (!winbind_name_to_sid_string(ctx, user, - current_name, - sid_list_buffer, - sid_list_buffer_size)) { - goto out; - } - - SAFE_FREE(current_name); - - if (!safe_append_string(sid_list_buffer, ",", - sid_list_buffer_size)) { - goto out; - } - - search_location = comma + 1; - } - - if (!winbind_name_to_sid_string(ctx, user, search_location, - sid_list_buffer, - sid_list_buffer_size)) { - goto out; - } - - result = true; - -out: - SAFE_FREE(current_name); - return result; -} - -/** - * put krb5ccname variable into environment - * - * @param ctx PAM winbind context. - * @param krb5ccname env variable retrieved from winbindd. - * - * @return void. - */ - -static void _pam_setup_krb5_env(struct pwb_context *ctx, - struct wbcLogonUserInfo *info) -{ - char var[PATH_MAX]; - int ret; - uint32_t i; - const char *krb5ccname = NULL; - - if (off(ctx->ctrl, WINBIND_KRB5_AUTH)) { - return; - } - - if (!info) { - return; - } - - for (i=0; i < info->num_blobs; i++) { - if (strcasecmp(info->blobs[i].name, "krb5ccname") == 0) { - krb5ccname = (const char *)info->blobs[i].blob.data; - break; - } - } - - if (!krb5ccname || (strlen(krb5ccname) == 0)) { - return; - } - - _pam_log_debug(ctx, LOG_DEBUG, - "request returned KRB5CCNAME: %s", krb5ccname); - - if (snprintf(var, sizeof(var), "KRB5CCNAME=%s", krb5ccname) == -1) { - return; - } - - ret = pam_putenv(ctx->pamh, var); - if (ret) { - _pam_log(ctx, LOG_ERR, - "failed to set KRB5CCNAME to %s: %s", - var, pam_strerror(ctx->pamh, ret)); - } -} - -/** - * Copy unix username if available (further processed in PAM). - * - * @param ctx PAM winbind context - * @param user_ret A pointer that holds a pointer to a string - * @param unix_username A username - * - * @return void. - */ - -static void _pam_setup_unix_username(struct pwb_context *ctx, - char **user_ret, - struct wbcLogonUserInfo *info) -{ - const char *unix_username = NULL; - uint32_t i; - - if (!user_ret || !info) { - return; - } - - for (i=0; i < info->num_blobs; i++) { - if (strcasecmp(info->blobs[i].name, "unix_username") == 0) { - unix_username = (const char *)info->blobs[i].blob.data; - break; - } - } - - if (!unix_username || !unix_username[0]) { - return; - } - - *user_ret = strdup(unix_username); -} - -/** - * Set string into the PAM stack. - * - * @param ctx PAM winbind context. - * @param data_name Key name for pam_set_data. - * @param value String value. - * - * @return void. - */ - -static void _pam_set_data_string(struct pwb_context *ctx, - const char *data_name, - const char *value) -{ - int ret; - - if (!data_name || !value || (strlen(data_name) == 0) || - (strlen(value) == 0)) { - return; - } - - ret = pam_set_data(ctx->pamh, data_name, talloc_strdup(NULL, value), - _pam_winbind_cleanup_func); - if (ret) { - _pam_log_debug(ctx, LOG_DEBUG, - "Could not set data %s: %s\n", - data_name, pam_strerror(ctx->pamh, ret)); - } -} - -/** - * Set info3 strings into the PAM stack. - * - * @param ctx PAM winbind context. - * @param data_name Key name for pam_set_data. - * @param value String value. - * - * @return void. - */ - -static void _pam_set_data_info3(struct pwb_context *ctx, - const struct wbcAuthUserInfo *info) -{ - _pam_set_data_string(ctx, PAM_WINBIND_HOMEDIR, - info->home_directory); - _pam_set_data_string(ctx, PAM_WINBIND_LOGONSCRIPT, - info->logon_script); - _pam_set_data_string(ctx, PAM_WINBIND_LOGONSERVER, - info->logon_server); - _pam_set_data_string(ctx, PAM_WINBIND_PROFILEPATH, - info->profile_path); -} - -/** - * Free info3 strings in the PAM stack. - * - * @param pamh PAM handle - * - * @return void. - */ - -static void _pam_free_data_info3(pam_handle_t *pamh) -{ - pam_set_data(pamh, PAM_WINBIND_HOMEDIR, NULL, NULL); - pam_set_data(pamh, PAM_WINBIND_LOGONSCRIPT, NULL, NULL); - pam_set_data(pamh, PAM_WINBIND_LOGONSERVER, NULL, NULL); - pam_set_data(pamh, PAM_WINBIND_PROFILEPATH, NULL, NULL); -} - -/** - * Send PAM_ERROR_MSG for cached or grace logons. - * - * @param ctx PAM winbind context. - * @param username User in PAM request. - * @param info3_user_flgs Info3 flags containing logon type bits. - * - * @return void. - */ - -static void _pam_warn_logon_type(struct pwb_context *ctx, - const char *username, - uint32_t info3_user_flgs) -{ - /* inform about logon type */ - if (PAM_WB_GRACE_LOGON(info3_user_flgs)) { - - _make_remark(ctx, PAM_ERROR_MSG, - _("Grace login. " - "Please change your password as soon you're " - "online again")); - _pam_log_debug(ctx, LOG_DEBUG, - "User %s logged on using grace logon\n", - username); - - } else if (PAM_WB_CACHED_LOGON(info3_user_flgs)) { - - _make_remark(ctx, PAM_ERROR_MSG, - _("Domain Controller unreachable, " - "using cached credentials instead. " - "Network resources may be unavailable")); - _pam_log_debug(ctx, LOG_DEBUG, - "User %s logged on using cached credentials\n", - username); - } -} - -/** - * Send PAM_ERROR_MSG for krb5 errors. - * - * @param ctx PAM winbind context. - * @param username User in PAM request. - * @param info3_user_flgs Info3 flags containing logon type bits. - * - * @return void. - */ - -static void _pam_warn_krb5_failure(struct pwb_context *ctx, - const char *username, - uint32_t info3_user_flgs) -{ - if (PAM_WB_KRB5_CLOCK_SKEW(info3_user_flgs)) { - _make_remark(ctx, PAM_ERROR_MSG, - _("Failed to establish your Kerberos Ticket cache " - "due time differences\n" - "with the domain controller. " - "Please verify the system time.\n")); - _pam_log_debug(ctx, LOG_DEBUG, - "User %s: Clock skew when getting Krb5 TGT\n", - username); - } -} - -static bool _pam_check_remark_auth_err(struct pwb_context *ctx, - const struct wbcAuthErrorInfo *e, - const char *nt_status_string, - int *pam_error) -{ - const char *ntstatus = NULL; - const char *error_string = NULL; - - if (!e || !pam_error) { - return false; - } - - ntstatus = e->nt_string; - if (!ntstatus) { - return false; - } - - if (strcasecmp(ntstatus, nt_status_string) == 0) { - - error_string = _get_ntstatus_error_string(nt_status_string); - if (error_string) { - _make_remark(ctx, PAM_ERROR_MSG, error_string); - *pam_error = e->pam_error; - return true; - } - - if (e->display_string) { - _make_remark(ctx, PAM_ERROR_MSG, e->display_string); - *pam_error = e->pam_error; - return true; - } - - _make_remark(ctx, PAM_ERROR_MSG, nt_status_string); - *pam_error = e->pam_error; - - return true; - } - - return false; -}; - -/** - * Compose Password Restriction String for a PAM_ERROR_MSG conversation. - * - * @param i The wbcUserPasswordPolicyInfo struct. - * - * @return string (caller needs to talloc_free). - */ - -static char *_pam_compose_pwd_restriction_string(struct pwb_context *ctx, - struct wbcUserPasswordPolicyInfo *i) -{ - char *str = NULL; - - if (!i) { - goto failed; - } - - str = talloc_asprintf(ctx, _("Your password ")); - if (!str) { - goto failed; - } - - if (i->min_length_password > 0) { - str = talloc_asprintf_append(str, - _("must be at least %d characters; "), - i->min_length_password); - if (!str) { - goto failed; - } - } - - if (i->password_history > 0) { - str = talloc_asprintf_append(str, - _("cannot repeat any of your previous %d " - "passwords; "), - i->password_history); - if (!str) { - goto failed; - } - } - - if (i->password_properties & WBC_DOMAIN_PASSWORD_COMPLEX) { - str = talloc_asprintf_append(str, - _("must contain capitals, numerals " - "or punctuation; " - "and cannot contain your account " - "or full name; ")); - if (!str) { - goto failed; - } - } - - str = talloc_asprintf_append(str, - _("Please type a different password. " - "Type a password which meets these requirements in " - "both text boxes.")); - if (!str) { - goto failed; - } - - return str; - - failed: - TALLOC_FREE(str); - return NULL; -} - -static int _pam_create_homedir(struct pwb_context *ctx, - const char *dirname, - mode_t mode) -{ - struct stat sbuf; - - if (stat(dirname, &sbuf) == 0) { - return PAM_SUCCESS; - } - - if (mkdir(dirname, mode) != 0) { - - _make_remark_format(ctx, PAM_TEXT_INFO, - _("Creating directory: %s failed: %s"), - dirname, strerror(errno)); - _pam_log(ctx, LOG_ERR, "could not create dir: %s (%s)", - dirname, strerror(errno)); - return PAM_PERM_DENIED; - } - - return PAM_SUCCESS; -} - -static int _pam_chown_homedir(struct pwb_context *ctx, - const char *dirname, - uid_t uid, - gid_t gid) -{ - if (chown(dirname, uid, gid) != 0) { - _pam_log(ctx, LOG_ERR, "failed to chown user homedir: %s (%s)", - dirname, strerror(errno)); - return PAM_PERM_DENIED; - } - - return PAM_SUCCESS; -} - -static int _pam_mkhomedir(struct pwb_context *ctx) -{ - struct passwd *pwd = NULL; - char *token = NULL; - char *create_dir = NULL; - char *user_dir = NULL; - int ret; - const char *username; - mode_t mode = 0700; - char *safe_ptr = NULL; - char *p = NULL; - - /* Get the username */ - ret = pam_get_user(ctx->pamh, &username, NULL); - if ((ret != PAM_SUCCESS) || (!username)) { - _pam_log_debug(ctx, LOG_DEBUG, "can not get the username"); - return PAM_SERVICE_ERR; - } - - pwd = getpwnam(username); - if (pwd == NULL) { - _pam_log_debug(ctx, LOG_DEBUG, "can not get the username"); - return PAM_USER_UNKNOWN; - } - _pam_log_debug(ctx, LOG_DEBUG, "homedir is: %s", pwd->pw_dir); - - ret = _pam_create_homedir(ctx, pwd->pw_dir, 0700); - if (ret == PAM_SUCCESS) { - ret = _pam_chown_homedir(ctx, pwd->pw_dir, - pwd->pw_uid, - pwd->pw_gid); - } - - if (ret == PAM_SUCCESS) { - return ret; - } - - /* maybe we need to create parent dirs */ - create_dir = talloc_strdup(ctx, "/"); - if (!create_dir) { - return PAM_BUF_ERR; - } - - /* find final directory */ - user_dir = strrchr(pwd->pw_dir, '/'); - if (!user_dir) { - return PAM_BUF_ERR; - } - user_dir++; - - _pam_log(ctx, LOG_DEBUG, "final directory: %s", user_dir); - - p = pwd->pw_dir; - - while ((token = strtok_r(p, "/", &safe_ptr)) != NULL) { - - mode = 0755; - - p = NULL; - - _pam_log_debug(ctx, LOG_DEBUG, "token is %s", token); - - create_dir = talloc_asprintf_append(create_dir, "%s/", token); - if (!create_dir) { - return PAM_BUF_ERR; - } - _pam_log_debug(ctx, LOG_DEBUG, "current_dir is %s", create_dir); - - if (strcmp(token, user_dir) == 0) { - _pam_log_debug(ctx, LOG_DEBUG, "assuming last directory: %s", token); - mode = 0700; - } - - ret = _pam_create_homedir(ctx, create_dir, mode); - if (ret) { - return ret; - } - } - - return _pam_chown_homedir(ctx, create_dir, - pwd->pw_uid, - pwd->pw_gid); -} - -/* talk to winbindd */ -static int winbind_auth_request(struct pwb_context *ctx, - const char *user, - const char *pass, - const char *member, - const char *cctype, - const int warn_pwd_expire, - struct wbcAuthErrorInfo **p_error, - struct wbcLogonUserInfo **p_info, - struct wbcUserPasswordPolicyInfo **p_policy, - time_t *pwd_last_set, - char **user_ret) -{ - wbcErr wbc_status; - - struct wbcLogonUserParams logon; - char membership_of[1024]; - uid_t user_uid = -1; - uint32_t flags = WBFLAG_PAM_INFO3_TEXT | - WBFLAG_PAM_GET_PWD_POLICY; - - struct wbcLogonUserInfo *info = NULL; - struct wbcAuthUserInfo *user_info = NULL; - struct wbcAuthErrorInfo *error = NULL; - struct wbcUserPasswordPolicyInfo *policy = NULL; - - int ret = PAM_AUTH_ERR; - int i; - const char *codes[] = { - "NT_STATUS_PASSWORD_EXPIRED", - "NT_STATUS_PASSWORD_MUST_CHANGE", - "NT_STATUS_INVALID_WORKSTATION", - "NT_STATUS_INVALID_LOGON_HOURS", - "NT_STATUS_ACCOUNT_EXPIRED", - "NT_STATUS_ACCOUNT_DISABLED", - "NT_STATUS_ACCOUNT_LOCKED_OUT", - "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", - "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", - "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", - "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", - "NT_STATUS_NO_LOGON_SERVERS", - "NT_STATUS_WRONG_PASSWORD", - "NT_STATUS_ACCESS_DENIED" - }; - - if (pwd_last_set) { - *pwd_last_set = 0; - } - - /* Krb5 auth always has to go against the KDC of the user's realm */ - - if (ctx->ctrl & WINBIND_KRB5_AUTH) { - flags |= WBFLAG_PAM_CONTACT_TRUSTDOM; - } - - if (ctx->ctrl & (WINBIND_KRB5_AUTH|WINBIND_CACHED_LOGIN)) { - struct passwd *pwd = NULL; - - pwd = getpwnam(user); - if (pwd == NULL) { - return PAM_USER_UNKNOWN; - } - user_uid = pwd->pw_uid; - } - - if (ctx->ctrl & WINBIND_KRB5_AUTH) { - - _pam_log_debug(ctx, LOG_DEBUG, - "enabling krb5 login flag\n"); - - flags |= WBFLAG_PAM_KRB5 | - WBFLAG_PAM_FALLBACK_AFTER_KRB5; - } - - if (ctx->ctrl & WINBIND_CACHED_LOGIN) { - _pam_log_debug(ctx, LOG_DEBUG, - "enabling cached login flag\n"); - flags |= WBFLAG_PAM_CACHED_LOGIN; - } - - if (user_ret) { - *user_ret = NULL; - flags |= WBFLAG_PAM_UNIX_NAME; - } - - if (cctype != NULL) { - _pam_log_debug(ctx, LOG_DEBUG, - "enabling request for a %s krb5 ccache\n", - cctype); - } - - if (member != NULL) { - - ZERO_STRUCT(membership_of); - - if (!winbind_name_list_to_sid_string_list(ctx, user, member, - membership_of, - sizeof(membership_of))) { - _pam_log_debug(ctx, LOG_ERR, - "failed to serialize membership of sid " - "\"%s\"\n", member); - return PAM_AUTH_ERR; - } - } - - ZERO_STRUCT(logon); - - logon.username = user; - logon.password = pass; - - if (cctype) { - wbc_status = wbcAddNamedBlob(&logon.num_blobs, - &logon.blobs, - "krb5_cc_type", - 0, - (uint8_t *)cctype, - strlen(cctype)+1); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto done; - } - } - - wbc_status = wbcAddNamedBlob(&logon.num_blobs, - &logon.blobs, - "flags", - 0, - (uint8_t *)&flags, - sizeof(flags)); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto done; - } - - wbc_status = wbcAddNamedBlob(&logon.num_blobs, - &logon.blobs, - "user_uid", - 0, - (uint8_t *)&user_uid, - sizeof(user_uid)); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto done; - } - - if (member) { - wbc_status = wbcAddNamedBlob(&logon.num_blobs, - &logon.blobs, - "membership_of", - 0, - (uint8_t *)membership_of, - sizeof(membership_of)); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto done; - } - } - - wbc_status = wbcLogonUser(&logon, &info, &error, &policy); - ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status, - user, "wbcLogonUser"); - wbcFreeMemory(logon.blobs); - logon.blobs = NULL; - - if (info && info->info) { - user_info = info->info; - } - - if (pwd_last_set && user_info) { - *pwd_last_set = user_info->pass_last_set_time; - } - - if (p_info && info) { - *p_info = info; - } - - if (p_policy && policy) { - *p_policy = policy; - } - - if (p_error && error) { - /* We want to process the error in the caller. */ - *p_error = error; - return ret; - } - - for (i=0; ipass_last_set_time; - - _pam_log_debug(ctx, LOG_DEBUG, - "Password has expired " - "(Password was last set: %lld, " - "the policy says it should expire here " - "%lld (now it's: %lu))\n", - (long long int)last_set, - (long long int)last_set + - policy->expire, - time(NULL)); - - return PAM_AUTHTOK_EXPIRED; - } - - /* inform about logon type */ - _pam_warn_logon_type(ctx, user, user_info->user_flags); - - /* inform about krb5 failures */ - _pam_warn_krb5_failure(ctx, user, user_info->user_flags); - - /* set some info3 info for other modules in the stack */ - _pam_set_data_info3(ctx, user_info); - - /* put krb5ccname into env */ - _pam_setup_krb5_env(ctx, info); - - /* If winbindd returned a username, return the pointer to it - * here. */ - _pam_setup_unix_username(ctx, user_ret, info); - } - - done: - if (logon.blobs) { - wbcFreeMemory(logon.blobs); - } - if (info && info->blobs) { - wbcFreeMemory(info->blobs); - } - if (error && !p_error) { - wbcFreeMemory(error); - } - if (info && !p_info) { - wbcFreeMemory(info); - } - if (policy && !p_policy) { - wbcFreeMemory(policy); - } - - return ret; -} - -/* talk to winbindd */ -static int winbind_chauthtok_request(struct pwb_context *ctx, - const char *user, - const char *oldpass, - const char *newpass, - time_t pwd_last_set) -{ - wbcErr wbc_status; - struct wbcChangePasswordParams params; - struct wbcAuthErrorInfo *error = NULL; - struct wbcUserPasswordPolicyInfo *policy = NULL; - enum wbcPasswordChangeRejectReason reject_reason = -1; - uint32_t flags = 0; - - int i; - const char *codes[] = { - "NT_STATUS_BACKUP_CONTROLLER", - "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", - "NT_STATUS_NO_LOGON_SERVERS", - "NT_STATUS_ACCESS_DENIED", - "NT_STATUS_PWD_TOO_SHORT", /* TODO: tell the min pwd length ? */ - "NT_STATUS_PWD_TOO_RECENT", /* TODO: tell the minage ? */ - "NT_STATUS_PWD_HISTORY_CONFLICT" /* TODO: tell the history length ? */ - }; - int ret = PAM_AUTH_ERR; - - ZERO_STRUCT(params); - - if (ctx->ctrl & WINBIND_KRB5_AUTH) { - flags |= WBFLAG_PAM_KRB5 | - WBFLAG_PAM_CONTACT_TRUSTDOM; - } - - if (ctx->ctrl & WINBIND_CACHED_LOGIN) { - flags |= WBFLAG_PAM_CACHED_LOGIN; - } - - params.account_name = user; - params.level = WBC_AUTH_USER_LEVEL_PLAIN; - params.old_password.plaintext = oldpass; - params.new_password.plaintext = newpass; - params.flags = flags; - - wbc_status = wbcChangeUserPasswordEx(¶ms, &error, &reject_reason, &policy); - ret = wbc_auth_error_to_pam_error(ctx, error, wbc_status, - user, "wbcChangeUserPasswordEx"); - - if (WBC_ERROR_IS_OK(wbc_status)) { - _pam_log(ctx, LOG_NOTICE, - "user '%s' password changed", user); - return PAM_SUCCESS; - } - - if (!error) { - wbcFreeMemory(policy); - return ret; - } - - for (i=0; int_string, - "NT_STATUS_PASSWORD_RESTRICTION")) { - - char *pwd_restriction_string = NULL; - SMB_TIME_T min_pwd_age = 0; - - if (policy) { - min_pwd_age = policy->min_passwordage; - } - - /* FIXME: avoid to send multiple PAM messages after another */ - switch (reject_reason) { - case -1: - break; - case WBC_PWD_CHANGE_REJECT_OTHER: - if ((min_pwd_age > 0) && - (pwd_last_set + min_pwd_age > time(NULL))) { - PAM_WB_REMARK_DIRECT(ctx, - "NT_STATUS_PWD_TOO_RECENT"); - } - break; - case WBC_PWD_CHANGE_REJECT_TOO_SHORT: - PAM_WB_REMARK_DIRECT(ctx, - "NT_STATUS_PWD_TOO_SHORT"); - break; - case WBC_PWD_CHANGE_REJECT_IN_HISTORY: - PAM_WB_REMARK_DIRECT(ctx, - "NT_STATUS_PWD_HISTORY_CONFLICT"); - break; - case WBC_PWD_CHANGE_REJECT_COMPLEXITY: - _make_remark(ctx, PAM_ERROR_MSG, - _("Password does not meet " - "complexity requirements")); - break; - default: - _pam_log_debug(ctx, LOG_DEBUG, - "unknown password change " - "reject reason: %d", - reject_reason); - break; - } - - pwd_restriction_string = - _pam_compose_pwd_restriction_string(ctx, policy); - if (pwd_restriction_string) { - _make_remark(ctx, PAM_ERROR_MSG, - pwd_restriction_string); - TALLOC_FREE(pwd_restriction_string); - } - } - done: - wbcFreeMemory(error); - wbcFreeMemory(policy); - - return ret; -} - -/* - * Checks if a user has an account - * - * return values: - * 1 = User not found - * 0 = OK - * -1 = System error - */ -static int valid_user(struct pwb_context *ctx, - const char *user) -{ - /* check not only if the user is available over NSS calls, also make - * sure it's really a winbind user, this is important when stacking PAM - * modules in the 'account' or 'password' facility. */ - - wbcErr wbc_status; - struct passwd *pwd = NULL; - struct passwd *wb_pwd = NULL; - - pwd = getpwnam(user); - if (pwd == NULL) { - return 1; - } - - wbc_status = wbcGetpwnam(user, &wb_pwd); - wbcFreeMemory(wb_pwd); - if (!WBC_ERROR_IS_OK(wbc_status)) { - _pam_log(ctx, LOG_DEBUG, "valid_user: wbcGetpwnam gave %s\n", - wbcErrorString(wbc_status)); - } - - switch (wbc_status) { - case WBC_ERR_UNKNOWN_USER: - return 1; - case WBC_ERR_SUCCESS: - return 0; - default: - break; - } - return -1; -} - -static char *_pam_delete(register char *xx) -{ - _pam_overwrite(xx); - _pam_drop(xx); - return NULL; -} - -/* - * obtain a password from the user - */ - -static int _winbind_read_password(struct pwb_context *ctx, - unsigned int ctrl, - const char *comment, - const char *prompt1, - const char *prompt2, - const char **pass) -{ - int authtok_flag; - int retval; - const char *item; - char *token; - - _pam_log(ctx, LOG_DEBUG, "getting password (0x%08x)", ctrl); - - /* - * make sure nothing inappropriate gets returned - */ - - *pass = token = NULL; - - /* - * which authentication token are we getting? - */ - - if (on(WINBIND__OLD_PASSWORD, ctrl)) { - authtok_flag = PAM_OLDAUTHTOK; - } else { - authtok_flag = PAM_AUTHTOK; - } - - /* - * should we obtain the password from a PAM item ? - */ - - if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || - on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - retval = _pam_get_item(ctx->pamh, authtok_flag, &item); - if (retval != PAM_SUCCESS) { - /* very strange. */ - _pam_log(ctx, LOG_ALERT, - "pam_get_item returned error " - "to unix-read-password"); - return retval; - } else if (item != NULL) { /* we have a password! */ - *pass = item; - item = NULL; - _pam_log(ctx, LOG_DEBUG, - "pam_get_item returned a password"); - return PAM_SUCCESS; - } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ - } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) - && off(WINBIND__OLD_PASSWORD, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; - } - } - /* - * getting here implies we will have to get the password from the - * user directly. - */ - - { - struct pam_message msg[3], *pmsg[3]; - struct pam_response *resp; - int i, replies; - - /* prepare to converse */ - - if (comment != NULL && off(ctrl, WINBIND_SILENT)) { - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = discard_const_p(char, comment); - i = 1; - } else { - i = 0; - } - - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = discard_const_p(char, prompt1); - replies = 1; - - if (prompt2 != NULL) { - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = discard_const_p(char, prompt2); - ++replies; - } - /* so call the conversation expecting i responses */ - resp = NULL; - retval = converse(ctx->pamh, i, pmsg, &resp); - if (resp == NULL) { - if (retval == PAM_SUCCESS) { - retval = PAM_AUTHTOK_RECOVER_ERR; - } - goto done; - } - if (retval != PAM_SUCCESS) { - _pam_drop_reply(resp, i); - goto done; - } - - /* interpret the response */ - - token = x_strdup(resp[i - replies].resp); - if (!token) { - _pam_log(ctx, LOG_NOTICE, - "could not recover " - "authentication token"); - retval = PAM_AUTHTOK_RECOVER_ERR; - goto done; - } - - if (replies == 2) { - /* verify that password entered correctly */ - if (!resp[i - 1].resp || - strcmp(token, resp[i - 1].resp)) { - _pam_delete(token); /* mistyped */ - retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(ctx, PAM_ERROR_MSG, - MISTYPED_PASS); - } - } - - /* - * tidy up the conversation (resp_retcode) is ignored - * -- what is it for anyway? AGM - */ - _pam_drop_reply(resp, i); - } - - done: - if (retval != PAM_SUCCESS) { - _pam_log_debug(ctx, LOG_DEBUG, - "unable to obtain a password"); - return retval; - } - /* 'token' is the entered password */ - - /* we store this password as an item */ - - retval = pam_set_item(ctx->pamh, authtok_flag, token); - _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS || - (retval = _pam_get_item(ctx->pamh, authtok_flag, &item)) != PAM_SUCCESS) { - - _pam_log(ctx, LOG_CRIT, "error manipulating password"); - return retval; - - } - - *pass = item; - item = NULL; /* break link to password */ - - return PAM_SUCCESS; -} - -static const char *get_conf_item_string(struct pwb_context *ctx, - const char *item, - int config_flag) -{ - int i = 0; - const char *parm_opt = NULL; - - if (!(ctx->ctrl & config_flag)) { - goto out; - } - - /* let the pam opt take precedence over the pam_winbind.conf option */ - for (i=0; iargc; i++) { - - if ((strncmp(ctx->argv[i], item, strlen(item)) == 0)) { - char *p; - - if ((p = strchr(ctx->argv[i], '=')) == NULL) { - _pam_log(ctx, LOG_INFO, - "no \"=\" delimiter for \"%s\" found\n", - item); - goto out; - } - _pam_log_debug(ctx, LOG_INFO, - "PAM config: %s '%s'\n", item, p+1); - return p + 1; - } - } - - if (ctx->dict) { - char *key = NULL; - - key = talloc_asprintf(ctx, "global:%s", item); - if (!key) { - goto out; - } - - parm_opt = iniparser_getstr(ctx->dict, key); - TALLOC_FREE(key); - - _pam_log_debug(ctx, LOG_INFO, "CONFIG file: %s '%s'\n", - item, parm_opt); - } -out: - return parm_opt; -} - -static int get_config_item_int(struct pwb_context *ctx, - const char *item, - int config_flag) -{ - int i, parm_opt = -1; - - if (!(ctx->ctrl & config_flag)) { - goto out; - } - - /* let the pam opt take precedence over the pam_winbind.conf option */ - for (i = 0; i < ctx->argc; i++) { - - if ((strncmp(ctx->argv[i], item, strlen(item)) == 0)) { - char *p; - - if ((p = strchr(ctx->argv[i], '=')) == NULL) { - _pam_log(ctx, LOG_INFO, - "no \"=\" delimiter for \"%s\" found\n", - item); - goto out; - } - parm_opt = atoi(p + 1); - _pam_log_debug(ctx, LOG_INFO, - "PAM config: %s '%d'\n", - item, parm_opt); - return parm_opt; - } - } - - if (ctx->dict) { - char *key = NULL; - - key = talloc_asprintf(ctx, "global:%s", item); - if (!key) { - goto out; - } - - parm_opt = iniparser_getint(ctx->dict, key, -1); - TALLOC_FREE(key); - - _pam_log_debug(ctx, LOG_INFO, - "CONFIG file: %s '%d'\n", - item, parm_opt); - } -out: - return parm_opt; -} - -static const char *get_krb5_cc_type_from_config(struct pwb_context *ctx) -{ - return get_conf_item_string(ctx, "krb5_ccache_type", - WINBIND_KRB5_CCACHE_TYPE); -} - -static const char *get_member_from_config(struct pwb_context *ctx) -{ - const char *ret = NULL; - ret = get_conf_item_string(ctx, "require_membership_of", - WINBIND_REQUIRED_MEMBERSHIP); - if (ret) { - return ret; - } - return get_conf_item_string(ctx, "require-membership-of", - WINBIND_REQUIRED_MEMBERSHIP); -} - -static int get_warn_pwd_expire_from_config(struct pwb_context *ctx) -{ - int ret; - ret = get_config_item_int(ctx, "warn_pwd_expire", - WINBIND_WARN_PWD_EXPIRE); - /* no or broken setting */ - if (ret <= 0) { - return DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES; - } - return ret; -} - -/** - * Retrieve the winbind separator. - * - * @param ctx PAM winbind context. - * - * @return string separator character. NULL on failure. - */ - -static char winbind_get_separator(struct pwb_context *ctx) -{ - wbcErr wbc_status; - static struct wbcInterfaceDetails *details = NULL; - - wbc_status = wbcInterfaceDetails(&details); - if (!WBC_ERROR_IS_OK(wbc_status)) { - _pam_log(ctx, LOG_ERR, - "Could not retrieve winbind interface details: %s", - wbcErrorString(wbc_status)); - return '\0'; - } - - if (!details) { - return '\0'; - } - - return details->winbind_separator; -} - - -/** - * Convert a upn to a name. - * - * @param ctx PAM winbind context. - * @param upn USer UPN to be trabslated. - * - * @return converted name. NULL pointer on failure. Caller needs to free. - */ - -static char* winbind_upn_to_username(struct pwb_context *ctx, - const char *upn) -{ - char sep; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - enum wbcSidType type; - char *domain; - char *name; - - /* This cannot work when the winbind separator = @ */ - - sep = winbind_get_separator(ctx); - if (!sep || sep == '@') { - return NULL; - } - - /* Convert the UPN to a SID */ - - wbc_status = wbcLookupName("", upn, &sid, &type); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return NULL; - } - - /* Convert the the SID back to the sAMAccountName */ - - wbc_status = wbcLookupSid(&sid, &domain, &name, &type); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return NULL; - } - - return talloc_asprintf(ctx, "%s\\%s", domain, name); -} - -static int _pam_delete_cred(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - int retval = PAM_SUCCESS; - struct pwb_context *ctx = NULL; - struct wbcLogoffUserParams logoff; - struct wbcAuthErrorInfo *error = NULL; - const char *user; - wbcErr wbc_status = WBC_ERR_SUCCESS; - - retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (retval) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("_pam_delete_cred", ctx); - - if (ctx->ctrl & WINBIND_KRB5_AUTH) { - - /* destroy the ccache here */ - - uint32_t wbc_flags = 0; - const char *ccname = NULL; - struct passwd *pwd = NULL; - - retval = pam_get_user(pamh, &user, _("Username: ")); - if (retval) { - _pam_log(ctx, LOG_ERR, - "could not identify user"); - goto out; - } - - if (user == NULL) { - _pam_log(ctx, LOG_ERR, - "username was NULL!"); - retval = PAM_USER_UNKNOWN; - goto out; - } - - _pam_log_debug(ctx, LOG_DEBUG, - "username [%s] obtained", user); - - ccname = pam_getenv(pamh, "KRB5CCNAME"); - if (ccname == NULL) { - _pam_log_debug(ctx, LOG_DEBUG, - "user has no KRB5CCNAME environment"); - } - - pwd = getpwnam(user); - if (pwd == NULL) { - retval = PAM_USER_UNKNOWN; - goto out; - } - - wbc_flags = WBFLAG_PAM_KRB5 | - WBFLAG_PAM_CONTACT_TRUSTDOM; - - ZERO_STRUCT(logoff); - - logoff.username = user; - - if (ccname) { - wbc_status = wbcAddNamedBlob(&logoff.num_blobs, - &logoff.blobs, - "ccfilename", - 0, - (uint8_t *)ccname, - strlen(ccname)+1); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto out; - } - } - - wbc_status = wbcAddNamedBlob(&logoff.num_blobs, - &logoff.blobs, - "flags", - 0, - (uint8_t *)&wbc_flags, - sizeof(wbc_flags)); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto out; - } - - wbc_status = wbcAddNamedBlob(&logoff.num_blobs, - &logoff.blobs, - "user_uid", - 0, - (uint8_t *)&pwd->pw_uid, - sizeof(pwd->pw_uid)); - if (!WBC_ERROR_IS_OK(wbc_status)) { - goto out; - } - - wbc_status = wbcLogoffUserEx(&logoff, &error); - retval = wbc_auth_error_to_pam_error(ctx, error, wbc_status, - user, "wbcLogoffUser"); - wbcFreeMemory(error); - wbcFreeMemory(logoff.blobs); - - if (!WBC_ERROR_IS_OK(wbc_status)) { - _pam_log(ctx, LOG_INFO, - "failed to logoff user %s: %s\n", - user, wbcErrorString(wbc_status)); - } - } - -out: - if (logoff.blobs) { - wbcFreeMemory(logoff.blobs); - } - - if (!WBC_ERROR_IS_OK(wbc_status)) { - retval = wbc_auth_error_to_pam_error(ctx, error, wbc_status, - user, "wbcLogoffUser"); - } - - /* - * Delete the krb5 ccname variable from the PAM environment - * if it was set by winbind. - */ - if (ctx->ctrl & WINBIND_KRB5_AUTH) { - pam_putenv(pamh, "KRB5CCNAME"); - } - - _PAM_LOG_FUNCTION_LEAVE("_pam_delete_cred", ctx, retval); - - TALLOC_FREE(ctx); - - return retval; -} - -PAM_EXTERN -int pam_sm_authenticate(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - const char *username; - const char *password; - const char *member = NULL; - const char *cctype = NULL; - int warn_pwd_expire; - int retval = PAM_AUTH_ERR; - char *username_ret = NULL; - char *new_authtok_required = NULL; - char *real_username = NULL; - struct pwb_context *ctx = NULL; - - retval = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (retval) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("pam_sm_authenticate", ctx); - - /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!username)) { - _pam_log_debug(ctx, LOG_DEBUG, - "can not get the username"); - retval = PAM_SERVICE_ERR; - goto out; - } - - -#if defined(AIX) - /* Decode the user name since AIX does not support logn user - names by default. The name is encoded as _#uid. */ - - if (username[0] == '_') { - uid_t id = atoi(&username[1]); - struct passwd *pw = NULL; - - if ((id!=0) && ((pw = getpwuid(id)) != NULL)) { - real_username = strdup(pw->pw_name); - } - } -#endif - - if (!real_username) { - /* Just making a copy of the username we got from PAM */ - if ((real_username = strdup(username)) == NULL) { - _pam_log_debug(ctx, LOG_DEBUG, - "memory allocation failure when copying " - "username"); - retval = PAM_SERVICE_ERR; - goto out; - } - } - - /* Maybe this was a UPN */ - - if (strchr(real_username, '@') != NULL) { - char *samaccountname = NULL; - - samaccountname = winbind_upn_to_username(ctx, - real_username); - if (samaccountname) { - free(real_username); - real_username = strdup(samaccountname); - } - } - - retval = _winbind_read_password(ctx, ctx->ctrl, NULL, - _("Password: "), NULL, - &password); - - if (retval != PAM_SUCCESS) { - _pam_log(ctx, LOG_ERR, - "Could not retrieve user's password"); - retval = PAM_AUTHTOK_ERR; - goto out; - } - - /* Let's not give too much away in the log file */ - -#ifdef DEBUG_PASSWORD - _pam_log_debug(ctx, LOG_INFO, - "Verify user '%s' with password '%s'", - real_username, password); -#else - _pam_log_debug(ctx, LOG_INFO, - "Verify user '%s'", real_username); -#endif - - member = get_member_from_config(ctx); - cctype = get_krb5_cc_type_from_config(ctx); - warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); - - /* Now use the username to look up password */ - retval = winbind_auth_request(ctx, real_username, password, - member, cctype, warn_pwd_expire, - NULL, NULL, NULL, - NULL, &username_ret); - - if (retval == PAM_NEW_AUTHTOK_REQD || - retval == PAM_AUTHTOK_EXPIRED) { - - char *new_authtok_required_during_auth = NULL; - - new_authtok_required = talloc_asprintf(NULL, "%d", retval); - if (!new_authtok_required) { - retval = PAM_BUF_ERR; - goto out; - } - - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, - new_authtok_required, - _pam_winbind_cleanup_func); - - retval = PAM_SUCCESS; - - new_authtok_required_during_auth = talloc_asprintf(NULL, "%d", true); - if (!new_authtok_required_during_auth) { - retval = PAM_BUF_ERR; - goto out; - } - - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, - new_authtok_required_during_auth, - _pam_winbind_cleanup_func); - - goto out; - } - -out: - if (username_ret) { - pam_set_item (pamh, PAM_USER, username_ret); - _pam_log_debug(ctx, LOG_INFO, - "Returned user was '%s'", username_ret); - free(username_ret); - } - - if (real_username) { - free(real_username); - } - - if (!new_authtok_required) { - pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, NULL, NULL); - } - - if (retval != PAM_SUCCESS) { - _pam_free_data_info3(pamh); - } - - _PAM_LOG_FUNCTION_LEAVE("pam_sm_authenticate", ctx, retval); - - TALLOC_FREE(ctx); - - return retval; -} - -PAM_EXTERN -int pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - int ret = PAM_SYSTEM_ERR; - struct pwb_context *ctx = NULL; - - ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (ret) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("pam_sm_setcred", ctx); - - switch (flags & ~PAM_SILENT) { - - case PAM_DELETE_CRED: - ret = _pam_delete_cred(pamh, flags, argc, argv); - break; - case PAM_REFRESH_CRED: - _pam_log_debug(ctx, LOG_WARNING, - "PAM_REFRESH_CRED not implemented"); - ret = PAM_SUCCESS; - break; - case PAM_REINITIALIZE_CRED: - _pam_log_debug(ctx, LOG_WARNING, - "PAM_REINITIALIZE_CRED not implemented"); - ret = PAM_SUCCESS; - break; - case PAM_ESTABLISH_CRED: - _pam_log_debug(ctx, LOG_WARNING, - "PAM_ESTABLISH_CRED not implemented"); - ret = PAM_SUCCESS; - break; - default: - ret = PAM_SYSTEM_ERR; - break; - } - - out: - - _PAM_LOG_FUNCTION_LEAVE("pam_sm_setcred", ctx, ret); - - TALLOC_FREE(ctx); - - return ret; -} - -/* - * Account management. We want to verify that the account exists - * before returning PAM_SUCCESS - */ -PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - const char *username; - int ret = PAM_USER_UNKNOWN; - void *tmp = NULL; - struct pwb_context *ctx = NULL; - - ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (ret) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("pam_sm_acct_mgmt", ctx); - - - /* Get the username */ - ret = pam_get_user(pamh, &username, NULL); - if ((ret != PAM_SUCCESS) || (!username)) { - _pam_log_debug(ctx, LOG_DEBUG, - "can not get the username"); - ret = PAM_SERVICE_ERR; - goto out; - } - - /* Verify the username */ - ret = valid_user(ctx, username); - switch (ret) { - case -1: - /* some sort of system error. The log was already printed */ - ret = PAM_SERVICE_ERR; - goto out; - case 1: - /* the user does not exist */ - _pam_log_debug(ctx, LOG_NOTICE, "user '%s' not found", - username); - if (ctx->ctrl & WINBIND_UNKNOWN_OK_ARG) { - ret = PAM_IGNORE; - goto out; - } - ret = PAM_USER_UNKNOWN; - goto out; - case 0: - pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, - (const void **)&tmp); - if (tmp != NULL) { - ret = atoi((const char *)tmp); - switch (ret) { - case PAM_AUTHTOK_EXPIRED: - /* fall through, since new token is required in this case */ - case PAM_NEW_AUTHTOK_REQD: - _pam_log(ctx, LOG_WARNING, - "pam_sm_acct_mgmt success but %s is set", - PAM_WINBIND_NEW_AUTHTOK_REQD); - _pam_log(ctx, LOG_NOTICE, - "user '%s' needs new password", - username); - /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */ - ret = PAM_NEW_AUTHTOK_REQD; - goto out; - default: - _pam_log(ctx, LOG_WARNING, - "pam_sm_acct_mgmt success"); - _pam_log(ctx, LOG_NOTICE, - "user '%s' granted access", username); - ret = PAM_SUCCESS; - goto out; - } - } - - /* Otherwise, the authentication looked good */ - _pam_log(ctx, LOG_NOTICE, - "user '%s' granted access", username); - ret = PAM_SUCCESS; - goto out; - default: - /* we don't know anything about this return value */ - _pam_log(ctx, LOG_ERR, - "internal module error (ret = %d, user = '%s')", - ret, username); - ret = PAM_SERVICE_ERR; - goto out; - } - - /* should not be reached */ - ret = PAM_IGNORE; - - out: - - _PAM_LOG_FUNCTION_LEAVE("pam_sm_acct_mgmt", ctx, ret); - - TALLOC_FREE(ctx); - - return ret; -} - -PAM_EXTERN -int pam_sm_open_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - int ret = PAM_SUCCESS; - struct pwb_context *ctx = NULL; - - ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (ret) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("pam_sm_open_session", ctx); - - if (ctx->ctrl & WINBIND_MKHOMEDIR) { - /* check and create homedir */ - ret = _pam_mkhomedir(ctx); - } - out: - _PAM_LOG_FUNCTION_LEAVE("pam_sm_open_session", ctx, ret); - - TALLOC_FREE(ctx); - - return ret; -} - -PAM_EXTERN -int pam_sm_close_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - int ret = PAM_SUCCESS; - struct pwb_context *ctx = NULL; - - ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (ret) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("pam_sm_close_session", ctx); - -out: - _PAM_LOG_FUNCTION_LEAVE("pam_sm_close_session", ctx, ret); - - TALLOC_FREE(ctx); - - return ret; -} - -/** - * evaluate whether we need to re-authenticate with kerberos after a - * password change - * - * @param ctx PAM winbind context. - * @param user The username - * - * @return boolean Returns true if required, false if not. - */ - -static bool _pam_require_krb5_auth_after_chauthtok(struct pwb_context *ctx, - const char *user) -{ - - /* Make sure that we only do this if a) the chauthtok got initiated - * during a logon attempt (authenticate->acct_mgmt->chauthtok) b) any - * later password change via the "passwd" command if done by the user - * itself - * NB. If we login from gdm or xdm and the password expires, - * we change the password, but there is no memory cache. - * Thus, even for passthrough login, we should do the - * authentication again to update memory cache. - * --- BoYang - * */ - - char *new_authtok_reqd_during_auth = NULL; - struct passwd *pwd = NULL; - - _pam_get_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, - &new_authtok_reqd_during_auth); - pam_set_data(ctx->pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, - NULL, NULL); - - if (new_authtok_reqd_during_auth) { - return true; - } - - pwd = getpwnam(user); - if (!pwd) { - return false; - } - - if (getuid() == pwd->pw_uid) { - return true; - } - - return false; -} - - -PAM_EXTERN -int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - unsigned int lctrl; - int ret; - bool cached_login = false; - - /* */ - const char *user; - char *pass_old, *pass_new; - /* */ - - char *Announce; - - int retry = 0; - char *username_ret = NULL; - struct wbcAuthErrorInfo *error = NULL; - struct pwb_context *ctx = NULL; - - ret = _pam_winbind_init_context(pamh, flags, argc, argv, &ctx); - if (ret) { - goto out; - } - - _PAM_LOG_FUNCTION_ENTER("pam_sm_chauthtok", ctx); - - cached_login = (ctx->ctrl & WINBIND_CACHED_LOGIN); - - /* clearing offline bit for auth */ - ctx->ctrl &= ~WINBIND_CACHED_LOGIN; - - /* - * First get the name of a user - */ - ret = pam_get_user(pamh, &user, _("Username: ")); - if (ret) { - _pam_log(ctx, LOG_ERR, - "password - could not identify user"); - goto out; - } - - if (user == NULL) { - _pam_log(ctx, LOG_ERR, "username was NULL!"); - ret = PAM_USER_UNKNOWN; - goto out; - } - - _pam_log_debug(ctx, LOG_DEBUG, "username [%s] obtained", user); - - /* check if this is really a user in winbindd, not only in NSS */ - ret = valid_user(ctx, user); - switch (ret) { - case 1: - ret = PAM_USER_UNKNOWN; - goto out; - case -1: - ret = PAM_SYSTEM_ERR; - goto out; - default: - break; - } - - /* - * obtain and verify the current password (OLDAUTHTOK) for - * the user. - */ - - if (flags & PAM_PRELIM_CHECK) { - time_t pwdlastset_prelim = 0; - - /* instruct user what is happening */ - -#define greeting _("Changing password for") - Announce = talloc_asprintf(ctx, "%s %s", greeting, user); - if (!Announce) { - _pam_log(ctx, LOG_CRIT, - "password - out of memory"); - ret = PAM_BUF_ERR; - goto out; - } -#undef greeting - - lctrl = ctx->ctrl | WINBIND__OLD_PASSWORD; - ret = _winbind_read_password(ctx, lctrl, - Announce, - _("(current) NT password: "), - NULL, - (const char **) &pass_old); - TALLOC_FREE(Announce); - if (ret != PAM_SUCCESS) { - _pam_log(ctx, LOG_NOTICE, - "password - (old) token not obtained"); - goto out; - } - - /* verify that this is the password for this user */ - - ret = winbind_auth_request(ctx, user, pass_old, - NULL, NULL, 0, - &error, NULL, NULL, - &pwdlastset_prelim, NULL); - - if (ret != PAM_ACCT_EXPIRED && - ret != PAM_AUTHTOK_EXPIRED && - ret != PAM_NEW_AUTHTOK_REQD && - ret != PAM_SUCCESS) { - pass_old = NULL; - goto out; - } - - pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, - (void *)pwdlastset_prelim, NULL); - - ret = pam_set_item(pamh, PAM_OLDAUTHTOK, - (const void *) pass_old); - pass_old = NULL; - if (ret != PAM_SUCCESS) { - _pam_log(ctx, LOG_CRIT, - "failed to set PAM_OLDAUTHTOK"); - } - } else if (flags & PAM_UPDATE_AUTHTOK) { - - time_t pwdlastset_update = 0; - - /* - * obtain the proposed password - */ - - /* - * get the old token back. - */ - - ret = _pam_get_item(pamh, PAM_OLDAUTHTOK, &pass_old); - - if (ret != PAM_SUCCESS) { - _pam_log(ctx, LOG_NOTICE, - "user not authenticated"); - goto out; - } - - lctrl = ctx->ctrl & ~WINBIND_TRY_FIRST_PASS_ARG; - - if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { - lctrl |= WINBIND_USE_FIRST_PASS_ARG; - } - retry = 0; - ret = PAM_AUTHTOK_ERR; - while ((ret != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { - /* - * use_authtok is to force the use of a previously entered - * password -- needed for pluggable password strength checking - */ - - ret = _winbind_read_password(ctx, lctrl, - NULL, - _("Enter new NT password: "), - _("Retype new NT password: "), - (const char **)&pass_new); - - if (ret != PAM_SUCCESS) { - _pam_log_debug(ctx, LOG_ALERT, - "password - " - "new password not obtained"); - pass_old = NULL;/* tidy up */ - goto out; - } - - /* - * At this point we know who the user is and what they - * propose as their new password. Verify that the new - * password is acceptable. - */ - - if (pass_new[0] == '\0') {/* "\0" password = NULL */ - pass_new = NULL; - } - } - - /* - * By reaching here we have approved the passwords and must now - * rebuild the password database file. - */ - _pam_get_data(pamh, PAM_WINBIND_PWD_LAST_SET, - &pwdlastset_update); - - /* - * if cached creds were enabled, make sure to set the - * WINBIND_CACHED_LOGIN bit here in order to have winbindd - * update the cached creds storage - gd - */ - if (cached_login) { - ctx->ctrl |= WINBIND_CACHED_LOGIN; - } - - ret = winbind_chauthtok_request(ctx, user, pass_old, - pass_new, pwdlastset_update); - if (ret) { - _pam_overwrite(pass_new); - _pam_overwrite(pass_old); - pass_old = pass_new = NULL; - goto out; - } - - if (_pam_require_krb5_auth_after_chauthtok(ctx, user)) { - - const char *member = NULL; - const char *cctype = NULL; - int warn_pwd_expire; - struct wbcLogonUserInfo *info = NULL; - struct wbcUserPasswordPolicyInfo *policy = NULL; - - member = get_member_from_config(ctx); - cctype = get_krb5_cc_type_from_config(ctx); - warn_pwd_expire = get_warn_pwd_expire_from_config(ctx); - - /* Keep WINBIND_CACHED_LOGIN bit for - * authentication after changing the password. - * This will update the cached credentials in case - * that winbindd_dual_pam_chauthtok() fails - * to update them. - * --- BoYang - * */ - - ret = winbind_auth_request(ctx, user, pass_new, - member, cctype, 0, - &error, &info, &policy, - NULL, &username_ret); - _pam_overwrite(pass_new); - _pam_overwrite(pass_old); - pass_old = pass_new = NULL; - - if (ret == PAM_SUCCESS) { - - struct wbcAuthUserInfo *user_info = NULL; - - if (info && info->info) { - user_info = info->info; - } - - /* warn a user if the password is about to - * expire soon */ - _pam_warn_password_expiry(ctx, user_info, policy, - warn_pwd_expire, - NULL); - - /* set some info3 info for other modules in the - * stack */ - _pam_set_data_info3(ctx, user_info); - - /* put krb5ccname into env */ - _pam_setup_krb5_env(ctx, info); - - if (username_ret) { - pam_set_item(pamh, PAM_USER, - username_ret); - _pam_log_debug(ctx, LOG_INFO, - "Returned user was '%s'", - username_ret); - free(username_ret); - } - - wbcFreeMemory(info); - wbcFreeMemory(policy); - } - - goto out; - } - } else { - ret = PAM_SERVICE_ERR; - } - -out: - { - /* Deal with offline errors. */ - int i; - const char *codes[] = { - "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", - "NT_STATUS_NO_LOGON_SERVERS", - "NT_STATUS_ACCESS_DENIED" - }; - - for (i=0; i 2000 - * Copyright (c) Tim Potter 2000 - * Copyright (c) Andrew Bartlettt 2002 - * Copyright (c) Guenther Deschner 2005-2008 - * Copyright (c) Jan Rêkorajski 1999. - * Copyright (c) Andrew G. Morgan 1996-8. - * Copyright (c) Alex O. Yuriev, 1996. - * Copyright (c) Cristian Gafton 1996. - * Copyright (C) Elliot Lee 1996, Red Hat Software. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h deleted file mode 100644 index 0656f5972e..0000000000 --- a/source3/nsswitch/pam_winbind.h +++ /dev/null @@ -1,170 +0,0 @@ -/* pam_winbind header file - (Solaris needs some macros from Linux for common PAM code) - - Shirish Kalele 2000 -*/ - -#include "../lib/replace/replace.h" -#include "system/syslog.h" -#include "system/time.h" -#include -#include "libwbclient/wbclient.h" -#include "localedir.h" - -#define MODULE_NAME "pam_winbind" -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#define PAM_SM_PASSWORD -#define PAM_SM_SESSION - -#ifndef PAM_WINBIND_CONFIG_FILE -#define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf" -#endif - -#include - -#ifdef HAVE_LIBINTL_H -#include -#endif - -#ifndef LINUX - -/* Solaris always uses dynamic pam modules */ -#define PAM_EXTERN extern -#if defined(HAVE_SECURITY_PAM_APPL_H) -#include -#elif defined(HAVE_PAM_PAM_APPL_H) -#include -#endif - -#ifndef PAM_AUTHTOK_RECOVER_ERR -#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR -#endif - -#endif /* defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD) || defined(AIX) */ - -#if defined(HAVE_SECURITY_PAM_MODULES_H) -#include -#elif defined(HAVE_PAM_PAM_MODULES_H) -#include -#endif - -#if defined(HAVE_SECURITY__PAM_MACROS_H) -#include -#elif defined(HAVE_PAM__PAM_MACROS_H) -#include -#else -/* Define required macros from (Linux PAM 0.68) security/_pam_macros.h */ -#define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \ -do { \ - int reply_i; \ - \ - for (reply_i=0; reply_i -#endif - -#define WINBIND_DEBUG_ARG 0x00000001 -#define WINBIND_USE_AUTHTOK_ARG 0x00000002 -#define WINBIND_UNKNOWN_OK_ARG 0x00000004 -#define WINBIND_TRY_FIRST_PASS_ARG 0x00000008 -#define WINBIND_USE_FIRST_PASS_ARG 0x00000010 -#define WINBIND__OLD_PASSWORD 0x00000020 -#define WINBIND_REQUIRED_MEMBERSHIP 0x00000040 -#define WINBIND_KRB5_AUTH 0x00000080 -#define WINBIND_KRB5_CCACHE_TYPE 0x00000100 -#define WINBIND_CACHED_LOGIN 0x00000200 -#define WINBIND_CONFIG_FILE 0x00000400 -#define WINBIND_SILENT 0x00000800 -#define WINBIND_DEBUG_STATE 0x00001000 -#define WINBIND_WARN_PWD_EXPIRE 0x00002000 -#define WINBIND_MKHOMEDIR 0x00004000 - -#if defined(HAVE_GETTEXT) && !defined(__LCLINT__) -#define _(string) dgettext(MODULE_NAME, string) -#else -#define _(string) string -#endif - -#define N_(string) string - -/* - * here is the string to inform the user that the new passwords they - * typed were not the same. - */ - -#define MISTYPED_PASS _("Sorry, passwords do not match") - -#define on(x, y) (x & y) -#define off(x, y) (!(x & y)) - -#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD" -#define PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH "PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH" -#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR" -#define PAM_WINBIND_LOGONSCRIPT "PAM_WINBIND_LOGONSCRIPT" -#define PAM_WINBIND_LOGONSERVER "PAM_WINBIND_LOGONSERVER" -#define PAM_WINBIND_PROFILEPATH "PAM_WINBIND_PROFILEPATH" -#define PAM_WINBIND_PWD_LAST_SET "PAM_WINBIND_PWD_LAST_SET" - -#define SECONDS_PER_DAY 86400 - -#define DEFAULT_DAYS_TO_WARN_BEFORE_PWD_EXPIRES 14 - -#include "winbind_client.h" - -#define PAM_WB_REMARK_DIRECT(c,x)\ -{\ - const char *error_string = NULL; \ - error_string = _get_ntstatus_error_string(x);\ - if (error_string != NULL) {\ - _make_remark(c, PAM_ERROR_MSG, error_string);\ - } else {\ - _make_remark(c, PAM_ERROR_MSG, x);\ - };\ -}; - -#define LOGON_KRB5_FAIL_CLOCK_SKEW 0x02000000 - -#define PAM_WB_CACHED_LOGON(x) (x & WBC_AUTH_USER_INFO_CACHED_ACCOUNT) -#define PAM_WB_KRB5_CLOCK_SKEW(x) (x & LOGON_KRB5_FAIL_CLOCK_SKEW) -#define PAM_WB_GRACE_LOGON(x) ((WBC_AUTH_USER_INFO_CACHED_ACCOUNT|WBC_AUTH_USER_INFO_GRACE_LOGON) == ( x & (WBC_AUTH_USER_INFO_CACHED_ACCOUNT|WBC_AUTH_USER_INFO_GRACE_LOGON))) - -struct pwb_context { - pam_handle_t *pamh; - int flags; - int argc; - const char **argv; - dictionary *dict; - uint32_t ctrl; -}; - -#define TALLOC_FREE(ctx) do { if ((ctx) != NULL) {talloc_free(ctx); ctx=NULL;} } while(0) -#define TALLOC_ZERO_P(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) -#define TALLOC_P(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) - diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c deleted file mode 100644 index a1646215bd..0000000000 --- a/source3/nsswitch/wb_common.c +++ /dev/null @@ -1,690 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - winbind client common code - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Andrew Bartlett 2002 - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "winbind_client.h" - -/* Global variables. These are effectively the client state information */ - -int winbindd_fd = -1; /* fd for winbindd socket */ -static int is_privileged = 0; - -/* Free a response structure */ - -void winbindd_free_response(struct winbindd_response *response) -{ - /* Free any allocated extra_data */ - - if (response) - SAFE_FREE(response->extra_data.data); -} - -/* Initialise a request structure */ - -void winbindd_init_request(struct winbindd_request *request, int request_type) -{ - request->length = sizeof(struct winbindd_request); - - request->cmd = (enum winbindd_cmd)request_type; - request->pid = getpid(); - -} - -/* Initialise a response structure */ - -static void init_response(struct winbindd_response *response) -{ - /* Initialise return value */ - - response->result = WINBINDD_ERROR; -} - -/* Close established socket */ - -void winbind_close_sock(void) -{ - if (winbindd_fd != -1) { - close(winbindd_fd); - winbindd_fd = -1; - } -} - -#define CONNECT_TIMEOUT 30 - -/* Make sure socket handle isn't stdin, stdout or stderr */ -#define RECURSION_LIMIT 3 - -static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) -{ - int new_fd; - if (fd >= 0 && fd <= 2) { -#ifdef F_DUPFD - if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { - return -1; - } - /* Paranoia */ - if (new_fd < 3) { - close(new_fd); - return -1; - } - close(fd); - return new_fd; -#else - if (limit <= 0) - return -1; - - new_fd = dup(fd); - if (new_fd == -1) - return -1; - - /* use the program stack to hold our list of FDs to close */ - new_fd = make_nonstd_fd_internals(new_fd, limit - 1); - close(fd); - return new_fd; -#endif - } - return fd; -} - -/**************************************************************************** - Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, - else - if SYSV use O_NDELAY - if BSD use FNDELAY - Set close on exec also. -****************************************************************************/ - -static int make_safe_fd(int fd) -{ - int result, flags; - int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); - if (new_fd == -1) { - close(fd); - return -1; - } - - /* Socket should be nonblocking. */ -#ifdef O_NONBLOCK -#define FLAG_TO_SET O_NONBLOCK -#else -#ifdef SYSV -#define FLAG_TO_SET O_NDELAY -#else /* BSD */ -#define FLAG_TO_SET FNDELAY -#endif -#endif - - if ((flags = fcntl(new_fd, F_GETFL)) == -1) { - close(new_fd); - return -1; - } - - flags |= FLAG_TO_SET; - if (fcntl(new_fd, F_SETFL, flags) == -1) { - close(new_fd); - return -1; - } - -#undef FLAG_TO_SET - - /* Socket should be closed on exec() */ -#ifdef FD_CLOEXEC - result = flags = fcntl(new_fd, F_GETFD, 0); - if (flags >= 0) { - flags |= FD_CLOEXEC; - result = fcntl( new_fd, F_SETFD, flags ); - } - if (result < 0) { - close(new_fd); - return -1; - } -#endif - return new_fd; -} - -/* Connect to winbindd socket */ - -static int winbind_named_pipe_sock(const char *dir) -{ - struct sockaddr_un sunaddr; - struct stat st; - char *path = NULL; - int fd; - int wait_time; - int slept; - - /* Check permissions on unix socket directory */ - - if (lstat(dir, &st) == -1) { - errno = ENOENT; - return -1; - } - - if (!S_ISDIR(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - errno = ENOENT; - return -1; - } - - /* Connect to socket */ - - if (asprintf(&path, "%s/%s", dir, WINBINDD_SOCKET_NAME) < 0) { - return -1; - } - - ZERO_STRUCT(sunaddr); - sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); - - /* If socket file doesn't exist, don't bother trying to connect - with retry. This is an attempt to make the system usable when - the winbindd daemon is not running. */ - - if (lstat(path, &st) == -1) { - errno = ENOENT; - SAFE_FREE(path); - return -1; - } - - SAFE_FREE(path); - /* Check permissions on unix socket file */ - - if (!S_ISSOCK(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - errno = ENOENT; - return -1; - } - - /* Connect to socket */ - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return -1; - } - - /* Set socket non-blocking and close on exec. */ - - if ((fd = make_safe_fd( fd)) == -1) { - return fd; - } - - for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1; - wait_time += slept) { - struct timeval tv; - fd_set w_fds; - int ret; - int connect_errno = 0; - socklen_t errnosize; - - if (wait_time >= CONNECT_TIMEOUT) - goto error_out; - - switch (errno) { - case EINPROGRESS: - FD_ZERO(&w_fds); - FD_SET(fd, &w_fds); - tv.tv_sec = CONNECT_TIMEOUT - wait_time; - tv.tv_usec = 0; - - ret = select(fd + 1, NULL, &w_fds, NULL, &tv); - - if (ret > 0) { - errnosize = sizeof(connect_errno); - - ret = getsockopt(fd, SOL_SOCKET, - SO_ERROR, &connect_errno, &errnosize); - - if (ret >= 0 && connect_errno == 0) { - /* Connect succeed */ - goto out; - } - } - - slept = CONNECT_TIMEOUT; - break; - case EAGAIN: - slept = rand() % 3 + 1; - sleep(slept); - break; - default: - goto error_out; - } - - } - - out: - - return fd; - - error_out: - - close(fd); - return -1; -} - -static const char *winbindd_socket_dir(void) -{ -#ifdef SOCKET_WRAPPER - const char *env_dir; - - env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); - if (env_dir) { - return env_dir; - } -#endif - - return WINBINDD_SOCKET_DIR; -} - -/* Connect to winbindd socket */ - -static int winbind_open_pipe_sock(int recursing, int need_priv) -{ -#ifdef HAVE_UNIXSOCKET - static pid_t our_pid; - struct winbindd_request request; - struct winbindd_response response; - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (our_pid != getpid()) { - winbind_close_sock(); - our_pid = getpid(); - } - - if ((need_priv != 0) && (is_privileged == 0)) { - winbind_close_sock(); - } - - if (winbindd_fd != -1) { - return winbindd_fd; - } - - if (recursing) { - return -1; - } - - if ((winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir())) == -1) { - return -1; - } - - is_privileged = 0; - - /* version-check the socket */ - - request.wb_flags = WBFLAG_RECURSE; - if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { - winbind_close_sock(); - return -1; - } - - /* try and get priv pipe */ - - request.wb_flags = WBFLAG_RECURSE; - if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { - int fd; - if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) { - close(winbindd_fd); - winbindd_fd = fd; - is_privileged = 1; - } - } - - if ((need_priv != 0) && (is_privileged == 0)) { - return -1; - } - - SAFE_FREE(response.extra_data.data); - - return winbindd_fd; -#else - return -1; -#endif /* HAVE_UNIXSOCKET */ -} - -/* Write data to winbindd socket */ - -int winbind_write_sock(void *buffer, int count, int recursing, int need_priv) -{ - int result, nwritten; - - /* Open connection to winbind daemon */ - - restart: - - if (winbind_open_pipe_sock(recursing, need_priv) == -1) { - errno = ENOENT; - return -1; - } - - /* Write data to socket */ - - nwritten = 0; - - while(nwritten < count) { - struct timeval tv; - fd_set r_fds; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(winbindd_fd, &r_fds); - ZERO_STRUCT(tv); - - if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { - winbind_close_sock(); - return -1; /* Select error */ - } - - /* Write should be OK if fd not available for reading */ - - if (!FD_ISSET(winbindd_fd, &r_fds)) { - - /* Do the write */ - - result = write(winbindd_fd, - (char *)buffer + nwritten, - count - nwritten); - - if ((result == -1) || (result == 0)) { - - /* Write failed */ - - winbind_close_sock(); - return -1; - } - - nwritten += result; - - } else { - - /* Pipe has closed on remote end */ - - winbind_close_sock(); - goto restart; - } - } - - return nwritten; -} - -/* Read data from winbindd socket */ - -int winbind_read_sock(void *buffer, int count) -{ - int nread = 0; - int total_time = 0, selret; - - if (winbindd_fd == -1) { - return -1; - } - - /* Read data from socket */ - while(nread < count) { - struct timeval tv; - fd_set r_fds; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(winbindd_fd, &r_fds); - ZERO_STRUCT(tv); - /* Wait for 5 seconds for a reply. May need to parameterise this... */ - tv.tv_sec = 5; - - if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) { - winbind_close_sock(); - return -1; /* Select error */ - } - - if (selret == 0) { - /* Not ready for read yet... */ - if (total_time >= 30) { - /* Timeout */ - winbind_close_sock(); - return -1; - } - total_time += 5; - continue; - } - - if (FD_ISSET(winbindd_fd, &r_fds)) { - - /* Do the Read */ - - int result = read(winbindd_fd, (char *)buffer + nread, - count - nread); - - if ((result == -1) || (result == 0)) { - - /* Read failed. I think the only useful thing we - can do here is just return -1 and fail since the - transaction has failed half way through. */ - - winbind_close_sock(); - return -1; - } - - nread += result; - - } - } - - return nread; -} - -/* Read reply */ - -int winbindd_read_reply(struct winbindd_response *response) -{ - int result1, result2 = 0; - - if (!response) { - return -1; - } - - /* Read fixed length response */ - - result1 = winbind_read_sock(response, - sizeof(struct winbindd_response)); - if (result1 == -1) { - return -1; - } - - /* We actually send the pointer value of the extra_data field from - the server. This has no meaning in the client's address space - so we clear it out. */ - - response->extra_data.data = NULL; - - /* Read variable length response */ - - if (response->length > sizeof(struct winbindd_response)) { - int extra_data_len = response->length - - sizeof(struct winbindd_response); - - /* Mallocate memory for extra data */ - - if (!(response->extra_data.data = malloc(extra_data_len))) { - return -1; - } - - result2 = winbind_read_sock(response->extra_data.data, - extra_data_len); - if (result2 == -1) { - winbindd_free_response(response); - return -1; - } - } - - /* Return total amount of data read */ - - return result1 + result2; -} - -/* - * send simple types of requests - */ - -NSS_STATUS winbindd_send_request(int req_type, int need_priv, - struct winbindd_request *request) -{ - struct winbindd_request lrequest; - - /* Check for our tricky environment variable */ - - if (winbind_env_set()) { - return NSS_STATUS_NOTFOUND; - } - - if (!request) { - ZERO_STRUCT(lrequest); - request = &lrequest; - } - - /* Fill in request and send down pipe */ - - winbindd_init_request(request, req_type); - - if (winbind_write_sock(request, sizeof(*request), - request->wb_flags & WBFLAG_RECURSE, - need_priv) == -1) - { - /* Set ENOENT for consistency. Required by some apps */ - errno = ENOENT; - - return NSS_STATUS_UNAVAIL; - } - - if ((request->extra_len != 0) && - (winbind_write_sock(request->extra_data.data, - request->extra_len, - request->wb_flags & WBFLAG_RECURSE, - need_priv) == -1)) - { - /* Set ENOENT for consistency. Required by some apps */ - errno = ENOENT; - - return NSS_STATUS_UNAVAIL; - } - - return NSS_STATUS_SUCCESS; -} - -/* - * Get results from winbindd request - */ - -NSS_STATUS winbindd_get_response(struct winbindd_response *response) -{ - struct winbindd_response lresponse; - - if (!response) { - ZERO_STRUCT(lresponse); - response = &lresponse; - } - - init_response(response); - - /* Wait for reply */ - if (winbindd_read_reply(response) == -1) { - /* Set ENOENT for consistency. Required by some apps */ - errno = ENOENT; - - return NSS_STATUS_UNAVAIL; - } - - /* Throw away extra data if client didn't request it */ - if (response == &lresponse) { - winbindd_free_response(response); - } - - /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - return NSS_STATUS_NOTFOUND; - } - - return NSS_STATUS_SUCCESS; -} - -/* Handle simple types of requests */ - -NSS_STATUS winbindd_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - NSS_STATUS status = NSS_STATUS_UNAVAIL; - int count = 0; - - while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { - status = winbindd_send_request(req_type, 0, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - status = winbindd_get_response(response); - count += 1; - } - - return status; -} - -NSS_STATUS winbindd_priv_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - NSS_STATUS status = NSS_STATUS_UNAVAIL; - int count = 0; - - while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { - status = winbindd_send_request(req_type, 1, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - status = winbindd_get_response(response); - count += 1; - } - - return status; -} - -/************************************************************************* - ************************************************************************/ - -const char *nss_err_str(NSS_STATUS ret) -{ - switch (ret) { - case NSS_STATUS_TRYAGAIN: - return "NSS_STATUS_TRYAGAIN"; - case NSS_STATUS_SUCCESS: - return "NSS_STATUS_SUCCESS"; - case NSS_STATUS_NOTFOUND: - return "NSS_STATUS_NOTFOUND"; - case NSS_STATUS_UNAVAIL: - return "NSS_STATUS_UNAVAIL"; -#ifdef NSS_STATUS_RETURN - case NSS_STATUS_RETURN: - return "NSS_STATUS_RETURN"; -#endif - default: - return "UNKNOWN RETURN CODE!!!!!!!"; - } -} diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c deleted file mode 100644 index c85e210cc0..0000000000 --- a/source3/nsswitch/wbinfo.c +++ /dev/null @@ -1,1984 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind status program. - - Copyright (C) Tim Potter 2000-2003 - 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 3 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, see . -*/ - -#include "includes.h" -#include "winbind_client.h" -#include "libwbclient/wbclient.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -static struct wbcInterfaceDetails *init_interface_details(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - static struct wbcInterfaceDetails *details; - - if (details) { - return details; - } - - wbc_status = wbcInterfaceDetails(&details); - if (!WBC_ERROR_IS_OK(wbc_status)) { - d_fprintf(stderr, "could not obtain winbind interface details!\n"); - } - - return details; -} - -static char winbind_separator_int(bool strict) -{ - struct wbcInterfaceDetails *details; - static bool got_sep; - static char sep; - - if (got_sep) - return sep; - - details = init_interface_details(); - - if (!details) { - d_fprintf(stderr, "could not obtain winbind separator!\n"); - if (strict) { - return 0; - } - /* HACK: (this module should not call lp_ funtions) */ - return *lp_winbind_separator(); - } - - sep = details->winbind_separator; - got_sep = true; - - if (!sep) { - d_fprintf(stderr, "winbind separator was NULL!\n"); - if (strict) { - return 0; - } - /* HACK: (this module should not call lp_ funtions) */ - sep = *lp_winbind_separator(); - } - - return sep; -} - -static char winbind_separator(void) -{ - return winbind_separator_int(false); -} - -static const char *get_winbind_domain(void) -{ - static struct wbcInterfaceDetails *details; - - details = init_interface_details(); - - if (!details) { - d_fprintf(stderr, "could not obtain winbind domain name!\n"); - - /* HACK: (this module should not call lp_ functions) */ - return lp_workgroup(); - } - - return details->netbios_domain; -} - -/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the - form DOMAIN/user into a domain and a user */ - -static bool parse_wbinfo_domain_user(const char *domuser, fstring domain, - fstring user) -{ - - char *p = strchr(domuser,winbind_separator()); - - if (!p) { - /* Maybe it was a UPN? */ - if ((p = strchr(domuser, '@')) != NULL) { - fstrcpy(domain, ""); - fstrcpy(user, domuser); - return true; - } - - fstrcpy(user, domuser); - fstrcpy(domain, get_winbind_domain()); - return true; - } - - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - strupper_m(domain); - - return true; -} - -/* Parse string of "uid,sid" or "gid,sid" into separate int and string values. - * Return true if input was valid, false otherwise. */ -static bool parse_mapping_arg(char *arg, int *id, char **sid) -{ - char *tmp, *endptr; - - if (!arg || !*arg) - return false; - - tmp = strtok(arg, ","); - *sid = strtok(NULL, ","); - - if (!tmp || !*tmp || !*sid || !**sid) - return false; - - /* Because atoi() can return 0 on invalid input, which would be a valid - * UID/GID we must use strtoul() and do error checking */ - *id = strtoul(tmp, &endptr, 10); - - if (endptr[0] != '\0') - return false; - - return true; -} - -/* pull pwent info for a given user */ - -static bool wbinfo_get_userinfo(char *user) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct passwd *pwd = NULL; - - wbc_status = wbcGetpwnam(user, &pwd); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - d_printf("%s:%s:%d:%d:%s:%s:%s\n", - pwd->pw_name, - pwd->pw_passwd, - pwd->pw_uid, - pwd->pw_gid, - pwd->pw_gecos, - pwd->pw_dir, - pwd->pw_shell); - - return true; -} - -/* pull pwent info for a given uid */ -static bool wbinfo_get_uidinfo(int uid) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct passwd *pwd = NULL; - - wbc_status = wbcGetpwuid(uid, &pwd); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - d_printf("%s:%s:%d:%d:%s:%s:%s\n", - pwd->pw_name, - pwd->pw_passwd, - pwd->pw_uid, - pwd->pw_gid, - pwd->pw_gecos, - pwd->pw_dir, - pwd->pw_shell); - - return true; -} - -/* pull grent for a given group */ -static bool wbinfo_get_groupinfo(const char *group) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct group *grp; - - wbc_status = wbcGetgrnam(group, &grp); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - d_printf("%s:%s:%d\n", - grp->gr_name, - grp->gr_passwd, - grp->gr_gid); - - wbcFreeMemory(grp); - - return true; -} - -/* List groups a user is a member of */ - -static bool wbinfo_get_usergroups(const char *user) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uint32_t num_groups; - uint32_t i; - gid_t *groups = NULL; - - /* Send request */ - - wbc_status = wbcGetGroups(user, &num_groups, &groups); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - for (i = 0; i < num_groups; i++) { - d_printf("%d\n", (int)groups[i]); - } - - wbcFreeMemory(groups); - - return true; -} - - -/* List group SIDs a user SID is a member of */ -static bool wbinfo_get_usersids(const char *user_sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uint32_t num_sids; - uint32_t i; - struct wbcDomainSid user_sid, *sids = NULL; - - /* Send request */ - - wbc_status = wbcStringToSid(user_sid_str, &user_sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcLookupUserSids(&user_sid, false, &num_sids, &sids); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - for (i = 0; i < num_sids; i++) { - char *str = NULL; - wbc_status = wbcSidToString(&sids[i], &str); - if (!WBC_ERROR_IS_OK(wbc_status)) { - wbcFreeMemory(sids); - return false; - } - d_printf("%s\n", str); - wbcFreeMemory(str); - } - - wbcFreeMemory(sids); - - return true; -} - -static bool wbinfo_get_userdomgroups(const char *user_sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uint32_t num_sids; - uint32_t i; - struct wbcDomainSid user_sid, *sids = NULL; - - /* Send request */ - - wbc_status = wbcStringToSid(user_sid_str, &user_sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcLookupUserSids(&user_sid, true, &num_sids, &sids); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - for (i = 0; i < num_sids; i++) { - char *str = NULL; - wbc_status = wbcSidToString(&sids[i], &str); - if (!WBC_ERROR_IS_OK(wbc_status)) { - wbcFreeMemory(sids); - return false; - } - d_printf("%s\n", str); - wbcFreeMemory(str); - } - - wbcFreeMemory(sids); - - return true; -} - -/* Convert NetBIOS name to IP */ - -static bool wbinfo_wins_byname(const char *name) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *ip = NULL; - - wbc_status = wbcResolveWinsByName(name, &ip); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%s\n", ip); - - wbcFreeMemory(ip); - - return true; -} - -/* Convert IP to NetBIOS name */ - -static bool wbinfo_wins_byip(const char *ip) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - char *name = NULL; - - wbc_status = wbcResolveWinsByIP(ip, &name); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%s\n", name); - - wbcFreeMemory(name); - - return true; -} - -/* List all/trusted domains */ - -static bool wbinfo_list_domains(bool list_all_domains, bool verbose) -{ - struct wbcDomainInfo *domain_list = NULL; - size_t num_domains; - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - bool print_all = !list_all_domains && verbose; - int i; - - wbc_status = wbcListTrusts(&domain_list, &num_domains); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - if (print_all) { - d_printf("%-16s%-24s%-12s%-12s%-5s%-5s\n", - "Domain Name", "DNS Domain", "Trust Type", - "Transitive", "In", "Out"); - } - - for (i=0; isid, &sid_str); - if (!WBC_ERROR_IS_OK(wbc_status)) { - wbcFreeMemory(dinfo); - return false; - } - - /* Display response */ - - d_printf("Name : %s\n", dinfo->short_name); - d_printf("Alt_Name : %s\n", dinfo->dns_name); - - d_printf("SID : %s\n", sid_str); - - d_printf("Active Directory : %s\n", - (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_AD) ? "Yes" : "No"); - d_printf("Native : %s\n", - (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ? "Yes" : "No"); - - d_printf("Primary : %s\n", - (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ? "Yes" : "No"); - - wbcFreeMemory(sid_str); - wbcFreeMemory(dinfo); - - return true; -} - -/* Get a foreign DC's name */ -static bool wbinfo_getdcname(const char *domain_name) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - fstrcpy(request.domain_name, domain_name); - - /* Send request */ - - if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) != - NSS_STATUS_SUCCESS) { - d_fprintf(stderr, "Could not get dc name for %s\n", domain_name); - return false; - } - - /* Display response */ - - d_printf("%s\n", response.data.dc_name); - - return true; -} - -/* Find a DC */ -static bool wbinfo_dsgetdcname(const char *domain_name, uint32_t flags) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - fstrcpy(request.data.dsgetdcname.domain_name, domain_name); - request.data.dsgetdcname.flags = flags; - - request.flags |= DS_DIRECTORY_SERVICE_REQUIRED; - - /* Send request */ - - if (winbindd_request_response(WINBINDD_DSGETDCNAME, &request, &response) != - NSS_STATUS_SUCCESS) { - d_fprintf(stderr, "Could not find dc for %s\n", domain_name); - return false; - } - - /* Display response */ - - d_printf("%s\n", response.data.dsgetdcname.dc_unc); - d_printf("%s\n", response.data.dsgetdcname.dc_address); - d_printf("%d\n", response.data.dsgetdcname.dc_address_type); - d_printf("%s\n", response.data.dsgetdcname.domain_guid); - d_printf("%s\n", response.data.dsgetdcname.domain_name); - d_printf("%s\n", response.data.dsgetdcname.forest_name); - d_printf("0x%08x\n", response.data.dsgetdcname.dc_flags); - d_printf("%s\n", response.data.dsgetdcname.dc_site_name); - d_printf("%s\n", response.data.dsgetdcname.client_site_name); - - return true; -} - -/* Check trust account password */ - -static bool wbinfo_check_secret(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcAuthErrorInfo *error = NULL; - - wbc_status = wbcCheckTrustCredentials(NULL, &error); - - d_printf("checking the trust secret via RPC calls %s\n", - WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); - - if (wbc_status == WBC_ERR_AUTH_ERROR) { - d_fprintf(stderr, "error code was %s (0x%x)\n", - error->nt_string, error->nt_status); - wbcFreeMemory(error); - } - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - return true; -} - -/* Convert uid to sid */ - -static bool wbinfo_uid_to_sid(uid_t uid) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - char *sid_str = NULL; - - /* Send request */ - - wbc_status = wbcUidToSid(uid, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcSidToString(&sid, &sid_str); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%s\n", sid_str); - - wbcFreeMemory(sid_str); - - return true; -} - -/* Convert gid to sid */ - -static bool wbinfo_gid_to_sid(gid_t gid) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - char *sid_str = NULL; - - /* Send request */ - - wbc_status = wbcGidToSid(gid, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcSidToString(&sid, &sid_str); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%s\n", sid_str); - - wbcFreeMemory(sid_str); - - return true; -} - -/* Convert sid to uid */ - -static bool wbinfo_sid_to_uid(const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - uid_t uid; - - /* Send request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcSidToUid(&sid, &uid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%d\n", (int)uid); - - return true; -} - -static bool wbinfo_sid_to_gid(const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - gid_t gid; - - /* Send request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcSidToGid(&sid, &gid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%d\n", (int)gid); - - return true; -} - -static bool wbinfo_allocate_uid(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uid_t uid; - - /* Send request */ - - wbc_status = wbcAllocateUid(&uid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("New uid: %d\n", uid); - - return true; -} - -static bool wbinfo_allocate_gid(void) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - gid_t gid; - - /* Send request */ - - wbc_status = wbcAllocateGid(&gid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("New gid: %d\n", gid); - - return true; -} - -static bool wbinfo_set_uid_mapping(uid_t uid, const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - - /* Send request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcSetUidMapping(uid, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("uid %d now mapped to sid %s\n", uid, sid_str); - - return true; -} - -static bool wbinfo_set_gid_mapping(gid_t gid, const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - - /* Send request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcSetGidMapping(gid, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("gid %d now mapped to sid %s\n", gid, sid_str); - - return true; -} - -static bool wbinfo_remove_uid_mapping(uid_t uid, const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - - /* Send request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcRemoveUidMapping(uid, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("Removed uid %d to sid %s mapping\n", uid, sid_str); - - return true; -} - -static bool wbinfo_remove_gid_mapping(gid_t gid, const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - - /* Send request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcRemoveGidMapping(gid, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("Removed gid %d to sid %s mapping\n", gid, sid_str); - - return true; -} - -/* Convert sid to string */ - -static bool wbinfo_lookupsid(const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - char *domain; - char *name; - enum wbcSidType type; - - /* Send off request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcLookupSid(&sid, &domain, &name, &type); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%s%c%s %d\n", - domain, winbind_separator(), name, type); - - return true; -} - -/* Convert sid to fullname */ - -static bool wbinfo_lookupsid_fullname(const char *sid_str) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainSid sid; - char *domain; - char *name; - enum wbcSidType type; - - /* Send off request */ - - wbc_status = wbcStringToSid(sid_str, &sid); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - wbc_status = wbcGetDisplayName(&sid, &domain, &name, &type); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - /* Display response */ - - d_printf("%s%c%s %d\n", - domain, winbind_separator(), name, type); - - return true; -} - -/* Lookup a list of RIDs */ - -static bool wbinfo_lookuprids(const char *domain, const char *arg) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - struct wbcDomainInfo *dinfo = NULL; - char *domain_name = NULL; - const char **names = NULL; - enum wbcSidType *types = NULL; - size_t i; - int num_rids; - uint32 *rids = NULL; - const char *p; - char *ridstr; - TALLOC_CTX *mem_ctx = NULL; - bool ret = false; - - if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) { - domain = get_winbind_domain(); - } - - /* Send request */ - - wbc_status = wbcDomainInfo(domain, &dinfo); - if (!WBC_ERROR_IS_OK(wbc_status)) { - d_printf("wbcDomainInfo(%s) failed: %s\n", domain, - wbcErrorString(wbc_status)); - goto done; - } - - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { - d_printf("talloc_new failed\n"); - goto done; - } - - num_rids = 0; - rids = NULL; - p = arg; - - while (next_token_talloc(mem_ctx, &p, &ridstr, " ,\n")) { - uint32 rid = strtoul(ridstr, NULL, 10); - ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids); - } - - if (rids == NULL) { - d_printf("no rids\n"); - goto done; - } - - wbc_status = wbcLookupRids(&dinfo->sid, num_rids, rids, - (const char **)&domain_name, &names, &types); - if (!WBC_ERROR_IS_OK(wbc_status)) { - d_printf("winbind_lookup_rids failed: %s\n", - wbcErrorString(wbc_status)); - goto done; - } - - d_printf("Domain: %s\n", domain_name); - - for (i=0; int_string, - err->nt_status, - err->display_string); - wbcFreeMemory(err); - } else if (WBC_ERROR_IS_OK(wbc_status)) { - wbcFreeMemory(info); - } - - data_blob_free(&nt); - data_blob_free(&lm); - SAFE_FREE(pass); - - return WBC_ERROR_IS_OK(wbc_status); -} - -/* Authenticate a user with a plaintext password and set a token */ - -static bool wbinfo_klog(char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(request.data.auth.user, username); - fstrcpy(request.data.auth.pass, p + 1); - *p = '%'; - } else { - fstrcpy(request.data.auth.user, username); - fstrcpy(request.data.auth.pass, getpass("Password: ")); - } - - request.flags |= WBFLAG_PAM_AFS_TOKEN; - - result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); - - /* Display response */ - - d_printf("plaintext password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status, - response.data.auth.error_string); - - if (result != NSS_STATUS_SUCCESS) - return false; - - if (response.extra_data.data == NULL) { - d_fprintf(stderr, "Did not get token data\n"); - return false; - } - - if (!afs_settoken_str((char *)response.extra_data.data)) { - d_fprintf(stderr, "Could not set token\n"); - return false; - } - - d_printf("Successfully created AFS token\n"); - return true; -} - -/* Print domain users */ - -static bool print_domain_users(const char *domain) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uint32_t i; - uint32_t num_users = 0; - const char **users = NULL; - - /* Send request to winbind daemon */ - - /* '.' is the special sign for our own domain */ - if (domain && strcmp(domain, ".") == 0) { - domain = get_winbind_domain(); - } - - wbc_status = wbcListUsers(domain, &num_users, &users); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - for (i=0; i < num_users; i++) { - d_printf("%s\n", users[i]); - } - - wbcFreeMemory(users); - - return true; -} - -/* Print domain groups */ - -static bool print_domain_groups(const char *domain) -{ - wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE; - uint32_t i; - uint32_t num_groups = 0; - const char **groups = NULL; - - /* Send request to winbind daemon */ - - /* '.' is the special sign for our own domain */ - if (domain && strcmp(domain, ".") == 0) { - domain = get_winbind_domain(); - } - - wbc_status = wbcListGroups(domain, &num_groups, &groups); - if (!WBC_ERROR_IS_OK(wbc_status)) { - return false; - } - - for (i=0; i < num_groups; i++) { - d_printf("%s\n", groups[i]); - } - - wbcFreeMemory(groups); - - return true; -} - -/* Set the authorised user for winbindd access in secrets.tdb */ - -static bool wbinfo_set_auth_user(char *username) -{ - const char *password; - char *p; - fstring user, domain; - - /* Separate into user and password */ - - parse_wbinfo_domain_user(username, domain, user); - - p = strchr(user, '%'); - - if (p != NULL) { - *p = 0; - password = p+1; - } else { - char *thepass = getpass("Password: "); - if (thepass) { - password = thepass; - } else - password = ""; - } - - /* Store or remove DOMAIN\username%password in secrets.tdb */ - - secrets_init(); - - if (user[0]) { - - if (!secrets_store(SECRETS_AUTH_USER, user, - strlen(user) + 1)) { - d_fprintf(stderr, "error storing username\n"); - return false; - } - - /* We always have a domain name added by the - parse_wbinfo_domain_user() function. */ - - if (!secrets_store(SECRETS_AUTH_DOMAIN, domain, - strlen(domain) + 1)) { - d_fprintf(stderr, "error storing domain name\n"); - return false; - } - - } else { - secrets_delete(SECRETS_AUTH_USER); - secrets_delete(SECRETS_AUTH_DOMAIN); - } - - if (password[0]) { - - if (!secrets_store(SECRETS_AUTH_PASSWORD, password, - strlen(password) + 1)) { - d_fprintf(stderr, "error storing password\n"); - return false; - } - - } else - secrets_delete(SECRETS_AUTH_PASSWORD); - - return true; -} - -static void wbinfo_get_auth_user(void) -{ - char *user, *domain, *password; - - /* Lift data from secrets file */ - - secrets_fetch_ipc_userpass(&user, &domain, &password); - - if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){ - - SAFE_FREE(user); - SAFE_FREE(domain); - SAFE_FREE(password); - d_printf("No authorised user configured\n"); - return; - } - - /* Pretty print authorised user info */ - - d_printf("%s%s%s%s%s\n", domain ? domain : "", domain ? lp_winbind_separator(): "", - user, password ? "%" : "", password ? password : ""); - - SAFE_FREE(user); - SAFE_FREE(domain); - SAFE_FREE(password); -} - -static bool wbinfo_ping(void) -{ - wbcErr wbc_status; - - wbc_status = wbcPing(); - - /* Display response */ - - d_printf("Ping to winbindd %s\n", - WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); - - return WBC_ERROR_IS_OK(wbc_status); -} - -static bool wbinfo_change_user_password(const char *username) -{ - wbcErr wbc_status; - char *old_password = NULL; - char *new_password = NULL; - - old_password = wbinfo_prompt_pass("old", username); - new_password = wbinfo_prompt_pass("new", username); - - wbc_status = wbcChangeUserPassword(username, old_password, new_password); - - /* Display response */ - - d_printf("Password change for user %s %s\n", username, - WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed"); - - SAFE_FREE(old_password); - SAFE_FREE(new_password); - - return WBC_ERROR_IS_OK(wbc_status); -} - -/* Main program */ - -enum { - OPT_SET_AUTH_USER = 1000, - OPT_GET_AUTH_USER, - OPT_DOMAIN_NAME, - OPT_SEQUENCE, - OPT_GETDCNAME, - OPT_DSGETDCNAME, - OPT_USERDOMGROUPS, - OPT_USERSIDS, - OPT_ALLOCATE_UID, - OPT_ALLOCATE_GID, - OPT_SET_UID_MAPPING, - OPT_SET_GID_MAPPING, - OPT_REMOVE_UID_MAPPING, - OPT_REMOVE_GID_MAPPING, - OPT_SEPARATOR, - OPT_LIST_ALL_DOMAINS, - OPT_LIST_OWN_DOMAIN, - OPT_UID_INFO, - OPT_GROUP_INFO, - OPT_VERBOSE, - OPT_ONLINESTATUS, - OPT_CHANGE_USER_PASSWORD, - OPT_SID_TO_FULLNAME -}; - -int main(int argc, char **argv, char **envp) -{ - int opt; - TALLOC_CTX *frame = talloc_stackframe(); - poptContext pc; - static char *string_arg; - char *string_subarg = NULL; - static char *opt_domain_name; - static int int_arg; - int int_subarg = -1; - int result = 1; - bool verbose = false; - - struct poptOption long_options[] = { - POPT_AUTOHELP - - /* longName, shortName, argInfo, argPtr, value, descrip, - argDesc */ - - { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"}, - { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" }, - { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" }, - { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" }, - { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, - { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, - { "sid-to-fullname", 0, POPT_ARG_STRING, &string_arg, - OPT_SID_TO_FULLNAME, "Converts sid to fullname", "SID" }, - { "lookup-rids", 'R', POPT_ARG_STRING, &string_arg, 'R', "Converts RIDs to names", "RIDs" }, - { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, - { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, - { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, - { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, - { "allocate-uid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_UID, - "Get a new UID out of idmap" }, - { "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID, - "Get a new GID out of idmap" }, - { "set-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_SET_UID_MAPPING, "Create or modify uid to sid mapping in idmap", "UID,SID" }, - { "set-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_SET_GID_MAPPING, "Create or modify gid to sid mapping in idmap", "GID,SID" }, - { "remove-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_UID_MAPPING, "Remove uid to sid mapping in idmap", "UID,SID" }, - { "remove-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_GID_MAPPING, "Remove gid to sid mapping in idmap", "GID,SID" }, - { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" }, - { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" }, - { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" }, - { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" }, - { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" }, - { "online-status", 0, POPT_ARG_NONE, 0, OPT_ONLINESTATUS, "Show whether domains are marked as online or offline"}, - { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" }, - { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" }, - { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" }, - { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" }, - { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, - { "user-domgroups", 0, POPT_ARG_STRING, &string_arg, - OPT_USERDOMGROUPS, "Get user domain groups", "SID" }, - { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" }, - { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, - { "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, - { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME, - "Get a DC name for a foreign domain", "domainname" }, - { "dsgetdcname", 0, POPT_ARG_STRING, &string_arg, OPT_DSGETDCNAME, "Find a DC for a domain", "domainname" }, - { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, - { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, - { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" }, -#ifdef WITH_FAKE_KASERVER - { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" }, -#endif -#ifdef HAVE_KRB5 - { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" }, - /* destroys wbinfo --help output */ - /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */ -#endif - { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL }, - { "verbose", 0, POPT_ARG_NONE, 0, OPT_VERBOSE, "Print additional information per command", NULL }, - { "change-user-password", 0, POPT_ARG_STRING, &string_arg, OPT_CHANGE_USER_PASSWORD, "Change the password for a user", NULL }, - POPT_COMMON_CONFIGFILE - POPT_COMMON_VERSION - POPT_TABLEEND - }; - - /* Samba client initialisation */ - load_case_tables(); - - - /* Parse options */ - - pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0); - - /* Parse command line options */ - - if (argc == 1) { - poptPrintHelp(pc, stderr, 0); - return 1; - } - - while((opt = poptGetNextOpt(pc)) != -1) { - /* get the generic configuration parameters like --domain */ - switch (opt) { - case OPT_VERBOSE: - verbose = True; - break; - } - } - - poptFreeContext(pc); - - if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, true)) { - d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n", - get_dyn_CONFIGFILE(), strerror(errno)); - exit(1); - } - - if (!init_names()) - return 1; - - load_interfaces(); - - pc = poptGetContext(NULL, argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - - while((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - case 'u': - if (!print_domain_users(opt_domain_name)) { - d_fprintf(stderr, "Error looking up domain users\n"); - goto done; - } - break; - case 'g': - if (!print_domain_groups(opt_domain_name)) { - d_fprintf(stderr, "Error looking up domain groups\n"); - goto done; - } - break; - case 's': - if (!wbinfo_lookupsid(string_arg)) { - d_fprintf(stderr, "Could not lookup sid %s\n", string_arg); - goto done; - } - break; - case OPT_SID_TO_FULLNAME: - if (!wbinfo_lookupsid_fullname(string_arg)) { - d_fprintf(stderr, "Could not lookup sid %s\n", - string_arg); - goto done; - } - break; - case 'R': - if (!wbinfo_lookuprids(opt_domain_name, string_arg)) { - d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg); - goto done; - } - break; - case 'n': - if (!wbinfo_lookupname(string_arg)) { - d_fprintf(stderr, "Could not lookup name %s\n", string_arg); - goto done; - } - break; - case 'N': - if (!wbinfo_wins_byname(string_arg)) { - d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg); - goto done; - } - break; - case 'I': - if (!wbinfo_wins_byip(string_arg)) { - d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg); - goto done; - } - break; - case 'U': - if (!wbinfo_uid_to_sid(int_arg)) { - d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg); - goto done; - } - break; - case 'G': - if (!wbinfo_gid_to_sid(int_arg)) { - d_fprintf(stderr, "Could not convert gid %d to sid\n", - int_arg); - goto done; - } - break; - case 'S': - if (!wbinfo_sid_to_uid(string_arg)) { - d_fprintf(stderr, "Could not convert sid %s to uid\n", - string_arg); - goto done; - } - break; - case 'Y': - if (!wbinfo_sid_to_gid(string_arg)) { - d_fprintf(stderr, "Could not convert sid %s to gid\n", - string_arg); - goto done; - } - break; - case OPT_ALLOCATE_UID: - if (!wbinfo_allocate_uid()) { - d_fprintf(stderr, "Could not allocate a uid\n"); - goto done; - } - break; - case OPT_ALLOCATE_GID: - if (!wbinfo_allocate_gid()) { - d_fprintf(stderr, "Could not allocate a gid\n"); - goto done; - } - break; - case OPT_SET_UID_MAPPING: - if (!parse_mapping_arg(string_arg, &int_subarg, - &string_subarg) || - !wbinfo_set_uid_mapping(int_subarg, string_subarg)) - { - d_fprintf(stderr, "Could not create or modify " - "uid to sid mapping\n"); - goto done; - } - break; - case OPT_SET_GID_MAPPING: - if (!parse_mapping_arg(string_arg, &int_subarg, - &string_subarg) || - !wbinfo_set_gid_mapping(int_subarg, string_subarg)) - { - d_fprintf(stderr, "Could not create or modify " - "gid to sid mapping\n"); - goto done; - } - break; - case OPT_REMOVE_UID_MAPPING: - if (!parse_mapping_arg(string_arg, &int_subarg, - &string_subarg) || - !wbinfo_remove_uid_mapping(int_subarg, - string_subarg)) - { - d_fprintf(stderr, "Could not remove uid to sid " - "mapping\n"); - goto done; - } - break; - case OPT_REMOVE_GID_MAPPING: - if (!parse_mapping_arg(string_arg, &int_subarg, - &string_subarg) || - !wbinfo_remove_gid_mapping(int_subarg, - string_subarg)) - { - d_fprintf(stderr, "Could not remove gid to sid " - "mapping\n"); - goto done; - } - break; - case 't': - if (!wbinfo_check_secret()) { - d_fprintf(stderr, "Could not check secret\n"); - goto done; - } - break; - case 'm': - if (!wbinfo_list_domains(false, verbose)) { - d_fprintf(stderr, "Could not list trusted domains\n"); - goto done; - } - break; - case OPT_SEQUENCE: - if (!wbinfo_show_sequence(opt_domain_name)) { - d_fprintf(stderr, "Could not show sequence numbers\n"); - goto done; - } - break; - case OPT_ONLINESTATUS: - if (!wbinfo_show_onlinestatus(opt_domain_name)) { - d_fprintf(stderr, "Could not show online-status\n"); - goto done; - } - break; - case 'D': - if (!wbinfo_domain_info(string_arg)) { - d_fprintf(stderr, "Could not get domain info\n"); - goto done; - } - break; - case 'i': - if (!wbinfo_get_userinfo(string_arg)) { - d_fprintf(stderr, "Could not get info for user %s\n", - string_arg); - goto done; - } - break; - case OPT_UID_INFO: - if ( !wbinfo_get_uidinfo(int_arg)) { - d_fprintf(stderr, "Could not get info for uid " - "%d\n", int_arg); - goto done; - } - break; - case OPT_GROUP_INFO: - if ( !wbinfo_get_groupinfo(string_arg)) { - d_fprintf(stderr, "Could not get info for " - "group %s\n", string_arg); - goto done; - } - break; - case 'r': - if (!wbinfo_get_usergroups(string_arg)) { - d_fprintf(stderr, "Could not get groups for user %s\n", - string_arg); - goto done; - } - break; - case OPT_USERSIDS: - if (!wbinfo_get_usersids(string_arg)) { - d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", - string_arg); - goto done; - } - break; - case OPT_USERDOMGROUPS: - if (!wbinfo_get_userdomgroups(string_arg)) { - d_fprintf(stderr, "Could not get user's domain groups " - "for user SID %s\n", string_arg); - goto done; - } - break; - case 'a': { - bool got_error = false; - - if (!wbinfo_auth(string_arg)) { - d_fprintf(stderr, "Could not authenticate user %s with " - "plaintext password\n", string_arg); - got_error = true; - } - - if (!wbinfo_auth_crap(string_arg)) { - d_fprintf(stderr, "Could not authenticate user %s with " - "challenge/response\n", string_arg); - got_error = true; - } - - if (got_error) - goto done; - break; - } - case 'K': { - uint32 flags = WBFLAG_PAM_KRB5 | - WBFLAG_PAM_CACHED_LOGIN | - WBFLAG_PAM_FALLBACK_AFTER_KRB5 | - WBFLAG_PAM_INFO3_TEXT; - - if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) { - d_fprintf(stderr, "Could not authenticate user [%s] with " - "Kerberos (ccache: %s)\n", string_arg, "FILE"); - goto done; - } - break; - } - case 'k': - if (!wbinfo_klog(string_arg)) { - d_fprintf(stderr, "Could not klog user\n"); - goto done; - } - break; - case 'p': - if (!wbinfo_ping()) { - d_fprintf(stderr, "could not ping winbindd!\n"); - goto done; - } - break; - case OPT_SET_AUTH_USER: - if (!wbinfo_set_auth_user(string_arg)) { - goto done; - } - break; - case OPT_GET_AUTH_USER: - wbinfo_get_auth_user(); - break; - case OPT_GETDCNAME: - if (!wbinfo_getdcname(string_arg)) { - goto done; - } - break; - case OPT_DSGETDCNAME: - if (!wbinfo_dsgetdcname(string_arg, 0)) { - goto done; - } - break; - case OPT_SEPARATOR: { - const char sep = winbind_separator_int(true); - if ( !sep ) { - goto done; - } - d_printf("%c\n", sep); - break; - } - case OPT_LIST_ALL_DOMAINS: - if (!wbinfo_list_domains(true, verbose)) { - goto done; - } - break; - case OPT_LIST_OWN_DOMAIN: - if (!wbinfo_list_own_domain()) { - goto done; - } - break; - case OPT_CHANGE_USER_PASSWORD: - if (!wbinfo_change_user_password(string_arg)) { - d_fprintf(stderr, "Could not change user password " - "for user %s\n", string_arg); - goto done; - } - break; - - /* generic configuration options */ - case OPT_DOMAIN_NAME: - break; - case OPT_VERBOSE: - break; - default: - d_fprintf(stderr, "Invalid option\n"); - poptPrintHelp(pc, stderr, 0); - goto done; - } - } - - result = 0; - - /* Exit code */ - - done: - talloc_destroy(frame); - - poptFreeContext(pc); - return result; -} diff --git a/source3/nsswitch/winbind_client.h b/source3/nsswitch/winbind_client.h deleted file mode 100644 index 757f5869e9..0000000000 --- a/source3/nsswitch/winbind_client.h +++ /dev/null @@ -1,30 +0,0 @@ -#include "winbind_nss_config.h" -#include "winbind_struct_protocol.h" - -void winbindd_init_request(struct winbindd_request *req,int rq_type); -void winbindd_free_response(struct winbindd_response *response); -NSS_STATUS winbindd_send_request(int req_type, int need_priv, - struct winbindd_request *request); -NSS_STATUS winbindd_get_response(struct winbindd_response *response); -NSS_STATUS winbindd_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); -NSS_STATUS winbindd_priv_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); -int winbindd_read_reply(struct winbindd_response *response); - -#define winbind_env_set() \ - (strcmp(getenv(WINBINDD_DONT_ENV)?getenv(WINBINDD_DONT_ENV):"0","1") == 0) - -#define winbind_off() \ - (setenv(WINBINDD_DONT_ENV, "1", 1) == 0) - -#define winbind_on() \ - (setenv(WINBINDD_DONT_ENV, "0", 1) == 0) - -int winbind_write_sock(void *buffer, int count, int recursing, int need_priv); -int winbind_read_sock(void *buffer, int count); -void winbind_close_sock(void); - -const char *nss_err_str(NSS_STATUS ret); diff --git a/source3/nsswitch/winbind_krb5_locator.c b/source3/nsswitch/winbind_krb5_locator.c deleted file mode 100644 index b9e35bdec5..0000000000 --- a/source3/nsswitch/winbind_krb5_locator.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - Unix SMB/CIFS implementation. - kerberos locator plugin - Copyright (C) Guenther Deschner 2007-2008 - - 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 3 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, see . -*/ - -#include "nsswitch/winbind_client.h" -#include "libwbclient/wbclient.h" - -#ifndef DEBUG_KRB5 -#undef DEBUG_KRB5 -#endif - -#if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H) - -#include - -#ifndef KRB5_PLUGIN_NO_HANDLE -#define KRB5_PLUGIN_NO_HANDLE KRB5_KDC_UNREACH /* Heimdal */ -#endif - -static const char *get_service_from_locate_service_type(enum locate_service_type svc) -{ - switch (svc) { - case locate_service_kdc: - case locate_service_master_kdc: - return "88"; - case locate_service_kadmin: - case locate_service_krb524: - /* not supported */ - return NULL; - case locate_service_kpasswd: - return "464"; - default: - break; - } - return NULL; - -} - -#ifdef DEBUG_KRB5 -static const char *locate_service_type_name(enum locate_service_type svc) -{ - switch (svc) { - case locate_service_kdc: - return "locate_service_kdc"; - case locate_service_master_kdc: - return "locate_service_master_kdc"; - case locate_service_kadmin: - return "locate_service_kadmin"; - case locate_service_krb524: - return "locate_service_krb524"; - case locate_service_kpasswd: - return "locate_service_kpasswd"; - default: - break; - } - return NULL; -} - -static const char *socktype_name(int socktype) -{ - switch (socktype) { - case SOCK_STREAM: - return "SOCK_STREAM"; - case SOCK_DGRAM: - return "SOCK_DGRAM"; - default: - break; - } - return "unknown"; -} - -static const char *family_name(int family) -{ - switch (family) { - case AF_UNSPEC: - return "AF_UNSPEC"; - case AF_INET: - return "AF_INET"; -#if defined(HAVE_IPV6) - case AF_INET6: - return "AF_INET6"; -#endif - default: - break; - } - return "unknown"; -} -#endif - -/** - * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones - * - * @param svc - * @param realm string - * @param socktype integer - * @param family integer - * - * @return integer. - */ - -static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc, - const char *realm, - int socktype, - int family) -{ - if (!realm || strlen(realm) == 0) { - return EINVAL; - } - - switch (svc) { - case locate_service_kdc: - case locate_service_master_kdc: - case locate_service_kpasswd: - break; - case locate_service_kadmin: - case locate_service_krb524: - return KRB5_PLUGIN_NO_HANDLE; - default: - return EINVAL; - } - - switch (family) { - case AF_UNSPEC: - case AF_INET: - break; -#if defined(HAVE_IPV6) - case AF_INET6: - break; -#endif - default: - return EINVAL; - } - - switch (socktype) { - case SOCK_STREAM: - case SOCK_DGRAM: - case 0: /* Heimdal uses that */ - break; - default: - return EINVAL; - } - - return 0; -} - -/** - * Try to get addrinfo for a given host and call the krb5 callback - * - * @param name string - * @param service string - * @param in struct addrinfo hint - * @param cbfunc krb5 callback function - * @param cbdata void pointer cbdata - * - * @return krb5_error_code. - */ - -static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name, - const char *service, - struct addrinfo *in, - int (*cbfunc)(void *, int, struct sockaddr *), - void *cbdata) -{ - struct addrinfo *out = NULL; - int ret; - int count = 3; - - while (count) { - - ret = getaddrinfo(name, service, in, &out); - if (ret == 0) { - break; - } - - if (ret == EAI_AGAIN) { - count--; - continue; - } - -#ifdef DEBUG_KRB5 - fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " - "getaddrinfo failed: %s (%d)\n", - (unsigned int)getpid(), gai_strerror(ret), ret); -#endif - - return KRB5_PLUGIN_NO_HANDLE; - } - - ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr); -#ifdef DEBUG_KRB5 - if (ret) { - fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " - "failed to call callback: %s (%d)\n", - (unsigned int)getpid(), error_message(ret), ret); - } -#endif - - freeaddrinfo(out); - return ret; -} - -/** - * PUBLIC INTERFACE: locate init - * - * @param context krb5_context - * @param privata_data pointer to private data pointer - * - * @return krb5_error_code. - */ - -static krb5_error_code smb_krb5_locator_init(krb5_context context, - void **private_data) -{ - return 0; -} - -/** - * PUBLIC INTERFACE: close locate - * - * @param private_data pointer to private data - * - * @return void. - */ - -static void smb_krb5_locator_close(void *private_data) -{ - return; -} - - -static bool ask_winbind(const char *realm, char **dcname) -{ - wbcErr wbc_status; - const char *dc = NULL; - struct wbcDomainControllerInfoEx *dc_info = NULL; - uint32_t flags; - - flags = WBC_LOOKUP_DC_KDC_REQUIRED | - WBC_LOOKUP_DC_IS_DNS_NAME | - WBC_LOOKUP_DC_RETURN_DNS_NAME | - WBC_LOOKUP_DC_IP_REQUIRED; - - wbc_status = wbcLookupDomainControllerEx(realm, NULL, NULL, flags, &dc_info); - - if (!WBC_ERROR_IS_OK(wbc_status)) { -#ifdef DEBUG_KRB5 - fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: failed with: %s\n", - (unsigned int)getpid(), wbcErrorString(wbc_status)); -#endif - return false; - } - - if (dc_info->dc_address) { - dc = dc_info->dc_address; - if (dc[0] == '\\') dc++; - if (dc[0] == '\\') dc++; - } - - if (!dc && dc_info->dc_unc) { - dc = dc_info->dc_unc; - if (dc[0] == '\\') dc++; - if (dc[0] == '\\') dc++; - } - - if (!dc) { - wbcFreeMemory(dc_info); - return false; - } - - *dcname = strdup(dc); - if (!*dcname) { - wbcFreeMemory(dc_info); - return false; - } - - wbcFreeMemory(dc_info); - return true; -} - -/** - * PUBLIC INTERFACE: locate lookup - * - * @param private_data pointer to private data - * @param svc enum locate_service_type. - * @param realm string - * @param socktype integer - * @param family integer - * @param cbfunc callback function to send back entries - * @param cbdata void pointer to cbdata - * - * @return krb5_error_code. - */ - -static krb5_error_code smb_krb5_locator_lookup(void *private_data, - enum locate_service_type svc, - const char *realm, - int socktype, - int family, - int (*cbfunc)(void *, int, struct sockaddr *), - void *cbdata) -{ - krb5_error_code ret; - struct addrinfo aihints; - char *kdc_name = NULL; - const char *service = get_service_from_locate_service_type(svc); - - ZERO_STRUCT(aihints); - -#ifdef DEBUG_KRB5 - fprintf(stderr,"[%5u]: smb_krb5_locator_lookup: called for '%s' " - "svc: '%s' (%d) " - "socktype: '%s' (%d), family: '%s' (%d)\n", - (unsigned int)getpid(), realm, - locate_service_type_name(svc), svc, - socktype_name(socktype), socktype, - family_name(family), family); -#endif - ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, - family); - if (ret) { -#ifdef DEBUG_KRB5 - fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " - "returning ret: %s (%d)\n", - (unsigned int)getpid(), error_message(ret), ret); -#endif - return ret; - } - - if (!winbind_env_set()) { - if (!ask_winbind(realm, &kdc_name)) { -#ifdef DEBUG_KRB5 - fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " - "failed to query winbindd\n", - (unsigned int)getpid()); -#endif - goto failed; - } - } else { - const char *env = NULL; - char *var = NULL; - if (asprintf(&var, "%s_%s", - WINBINDD_LOCATOR_KDC_ADDRESS, realm) == -1) { - goto failed; - } - env = getenv(var); - if (!env) { -#ifdef DEBUG_KRB5 - fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " - "failed to get kdc from env %s\n", - (unsigned int)getpid(), var); -#endif - free(var); - goto failed; - } - free(var); - - kdc_name = strdup(env); - if (!kdc_name) { - goto failed; - } - } -#ifdef DEBUG_KRB5 - fprintf(stderr, "[%5u]: smb_krb5_locator_lookup: " - "got '%s' for '%s' from winbindd\n", (unsigned int)getpid(), - kdc_name, realm); -#endif - - aihints.ai_family = family; - aihints.ai_socktype = socktype; - - ret = smb_krb5_locator_call_cbfunc(kdc_name, - service, - &aihints, - cbfunc, cbdata); - SAFE_FREE(kdc_name); - - return ret; - - failed: - return KRB5_PLUGIN_NO_HANDLE; -} - -#ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H -#define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */ -#else -#define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */ -#endif - -const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = { - 0, /* version */ - smb_krb5_locator_init, - smb_krb5_locator_close, - smb_krb5_locator_lookup, -}; - -#endif diff --git a/source3/nsswitch/winbind_nss.h b/source3/nsswitch/winbind_nss.h deleted file mode 100644 index 0a3bc7cefa..0000000000 --- a/source3/nsswitch/winbind_nss.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - A common place to work out how to define NSS_STATUS on various - platforms. - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _NSSWITCH_NSS_H -#define _NSSWITCH_NSS_H - -#ifdef HAVE_NSS_COMMON_H - -/* - * Sun Solaris - */ - -#include "nsswitch/winbind_nss_solaris.h" - -#elif HAVE_NSS_H - -/* - * Linux (glibc) - */ - -#include "nsswitch/winbind_nss_linux.h" - -#elif HAVE_NS_API_H - -/* - * SGI IRIX - */ - -#include "nsswitch/winbind_nss_irix.h" - -#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) - -/* HP-UX 11 */ - -#include "nsswitch/winbind_nss_hpux.h" - -#elif defined(__NetBSD__) && defined(HAVE_GETPWENT_R) - -/* - * NetBSD 3 and newer - */ - -#include "nsswitch/winbind_nss_netbsd.h" - -#else /* Nothing's defined. Neither gnu nor netbsd nor sun nor hp */ - -typedef enum -{ - NSS_STATUS_SUCCESS=0, - NSS_STATUS_NOTFOUND=1, - NSS_STATUS_UNAVAIL=2, - NSS_STATUS_TRYAGAIN=3 -} NSS_STATUS; - -#endif - -#endif /* _NSSWITCH_NSS_H */ diff --git a/source3/nsswitch/winbind_nss_aix.c b/source3/nsswitch/winbind_nss_aix.c deleted file mode 100644 index 9c84e5f8aa..0000000000 --- a/source3/nsswitch/winbind_nss_aix.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - AIX loadable authentication module, providing identification and - authentication routines against Samba winbind/Windows NT Domain - - Copyright (C) Tim Potter 2003 - Copyright (C) Steve Roylance 2003 - Copyright (C) Andrew Tridgell 2003-2004 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -/* - - To install this module copy nsswitch/WINBIND to /usr/lib/security and add - "WINBIND" in /usr/lib/security/methods.cfg and /etc/security/user - - Note that this module also provides authentication and password - changing routines, so you do not need to install the winbind PAM - module. - - see - http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/kernextc/sec_load_mod.htm - for some information in the interface that this module implements - - Many thanks to Julianne Haugh for explaining some of the finer - details of this interface. - - To debug this module use uess_test.c (which you can get from tridge) - or set "options=debug" in /usr/lib/security/methods.cfg - -*/ - -#include "winbind_client.h" -#include - -/* enable this to log which entry points have not been - completed yet */ -#define LOG_UNIMPLEMENTED_CALLS 0 - - -#define WB_AIX_ENCODED '_' - -static int debug_enabled; - - -static void logit(const char *format, ...) -{ - va_list ap; - FILE *f; - if (!debug_enabled) { - return; - } - f = fopen("/tmp/WINBIND_DEBUG.log", "a"); - if (!f) return; - va_start(ap, format); - vfprintf(f, format, ap); - va_end(ap); - fclose(f); -} - - -#define HANDLE_ERRORS(ret) do { \ - if ((ret) == NSS_STATUS_NOTFOUND) { \ - errno = ENOENT; \ - return NULL; \ - } else if ((ret) != NSS_STATUS_SUCCESS) { \ - errno = EIO; \ - return NULL; \ - } \ -} while (0) - -#define STRCPY_RET(dest, src) \ -do { \ - if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return -1; } \ - strcpy(dest, src); \ -} while (0) - -#define STRCPY_RETNULL(dest, src) \ -do { \ - if (strlen(src)+1 > sizeof(dest)) { errno = EINVAL; return NULL; } \ - strcpy(dest, src); \ -} while (0) - - -/* free a passwd structure */ -static void free_pwd(struct passwd *pwd) -{ - free(pwd->pw_name); - free(pwd->pw_passwd); - free(pwd->pw_gecos); - free(pwd->pw_dir); - free(pwd->pw_shell); - free(pwd); -} - -/* free a group structure */ -static void free_grp(struct group *grp) -{ - int i; - - free(grp->gr_name); - free(grp->gr_passwd); - - if (!grp->gr_mem) { - free(grp); - return; - } - - for (i=0; grp->gr_mem[i]; i++) { - free(grp->gr_mem[i]); - } - - free(grp->gr_mem); - free(grp); -} - - -/* replace commas with nulls, and null terminate */ -static void replace_commas(char *s) -{ - char *p, *p0=s; - for (p=strchr(s, ','); p; p = strchr(p+1, ',')) { - *p=0; - p0 = p+1; - } - - p0[strlen(p0)+1] = 0; -} - - -/* the decode_*() routines are used to cope with the fact that AIX 5.2 - and below cannot handle user or group names longer than 8 - characters in some interfaces. We use the normalize method to - provide a mapping to a username that fits, by using the form '_UID' - or '_GID'. - - this only works if you can guarantee that the WB_AIX_ENCODED char - is not used as the first char of any other username -*/ -static unsigned decode_id(const char *name) -{ - unsigned id; - sscanf(name+1, "%u", &id); - return id; -} - -static struct passwd *wb_aix_getpwuid(uid_t uid); - -static char *decode_user(const char *name) -{ - struct passwd *pwd; - unsigned id; - char *ret; - - sscanf(name+1, "%u", &id); - pwd = wb_aix_getpwuid(id); - if (!pwd) { - return NULL; - } - ret = strdup(pwd->pw_name); - - free_pwd(pwd); - - logit("decoded '%s' -> '%s'\n", name, ret); - - return ret; -} - - -/* - fill a struct passwd from a winbindd_pw struct, allocating as a single block -*/ -static struct passwd *fill_pwent(struct winbindd_pw *pw) -{ - struct passwd *result; - - result = calloc(1, sizeof(struct passwd)); - if (!result) { - errno = ENOMEM; - return NULL; - } - - result->pw_uid = pw->pw_uid; - result->pw_gid = pw->pw_gid; - result->pw_name = strdup(pw->pw_name); - result->pw_passwd = strdup(pw->pw_passwd); - result->pw_gecos = strdup(pw->pw_gecos); - result->pw_dir = strdup(pw->pw_dir); - result->pw_shell = strdup(pw->pw_shell); - - return result; -} - - -/* - fill a struct group from a winbindd_pw struct, allocating as a single block -*/ -static struct group *fill_grent(struct winbindd_gr *gr, char *gr_mem) -{ - int i; - struct group *result; - char *p, *name; - - result = calloc(1, sizeof(struct group)); - if (!result) { - errno = ENOMEM; - return NULL; - } - - result->gr_gid = gr->gr_gid; - - result->gr_name = strdup(gr->gr_name); - result->gr_passwd = strdup(gr->gr_passwd); - - /* Group membership */ - if ((gr->num_gr_mem < 0) || !gr_mem) { - gr->num_gr_mem = 0; - } - - if (gr->num_gr_mem == 0) { - /* Group is empty */ - return result; - } - - result->gr_mem = (char **)malloc(sizeof(char *) * (gr->num_gr_mem+1)); - if (!result->gr_mem) { - errno = ENOMEM; - return NULL; - } - - /* Start looking at extra data */ - i=0; - for (name = strtok_r(gr_mem, ",", &p); - name; - name = strtok_r(NULL, ",", &p)) { - if (i == gr->num_gr_mem) { - break; - } - result->gr_mem[i] = strdup(name); - i++; - } - - /* Terminate list */ - result->gr_mem[i] = NULL; - - return result; -} - - - -/* take a group id and return a filled struct group */ -static struct group *wb_aix_getgrgid(gid_t gid) -{ - struct winbindd_response response; - struct winbindd_request request; - struct group *grp; - NSS_STATUS ret; - - logit("getgrgid %d\n", gid); - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.gid = gid; - - ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response); - - logit("getgrgid ret=%d\n", ret); - - HANDLE_ERRORS(ret); - - grp = fill_grent(&response.data.gr, response.extra_data.data); - - winbindd_free_response(&response); - - return grp; -} - -/* take a group name and return a filled struct group */ -static struct group *wb_aix_getgrnam(const char *name) -{ - struct winbindd_response response; - struct winbindd_request request; - NSS_STATUS ret; - struct group *grp; - - if (*name == WB_AIX_ENCODED) { - return wb_aix_getgrgid(decode_id(name)); - } - - logit("getgrnam '%s'\n", name); - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - STRCPY_RETNULL(request.data.groupname, name); - - ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); - - HANDLE_ERRORS(ret); - - grp = fill_grent(&response.data.gr, response.extra_data.data); - - winbindd_free_response(&response); - - return grp; -} - - -/* this call doesn't have to fill in the gr_mem, but we do anyway - for simplicity */ -static struct group *wb_aix_getgracct(void *id, int type) -{ - if (type == 1) { - return wb_aix_getgrnam((char *)id); - } - if (type == 0) { - return wb_aix_getgrgid(*(int *)id); - } - errno = EINVAL; - return NULL; -} - - -/* take a username and return a string containing a comma-separated - list of group id numbers to which the user belongs */ -static char *wb_aix_getgrset(char *user) -{ - struct winbindd_response response; - struct winbindd_request request; - NSS_STATUS ret; - int i, idx; - char *tmpbuf; - int num_gids; - gid_t *gid_list; - char *r_user = user; - - if (*user == WB_AIX_ENCODED) { - r_user = decode_user(r_user); - if (!r_user) { - errno = ENOENT; - return NULL; - } - } - - logit("getgrset '%s'\n", r_user); - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - STRCPY_RETNULL(request.data.username, r_user); - - if (*user == WB_AIX_ENCODED) { - free(r_user); - } - - ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); - - HANDLE_ERRORS(ret); - - num_gids = response.data.num_entries; - gid_list = (gid_t *)response.extra_data.data; - - /* allocate a space large enough to contruct the string */ - tmpbuf = malloc(num_gids*12); - if (!tmpbuf) { - return NULL; - } - - for (idx=i=0; i < num_gids-1; i++) { - idx += sprintf(tmpbuf+idx, "%u,", gid_list[i]); - } - idx += sprintf(tmpbuf+idx, "%u", gid_list[i]); - - winbindd_free_response(&response); - - return tmpbuf; -} - - -/* take a uid and return a filled struct passwd */ -static struct passwd *wb_aix_getpwuid(uid_t uid) -{ - struct winbindd_response response; - struct winbindd_request request; - NSS_STATUS ret; - struct passwd *pwd; - - logit("getpwuid '%d'\n", uid); - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); - - HANDLE_ERRORS(ret); - - pwd = fill_pwent(&response.data.pw); - - winbindd_free_response(&response); - - logit("getpwuid gave ptr %p\n", pwd); - - return pwd; -} - - -/* take a username and return a filled struct passwd */ -static struct passwd *wb_aix_getpwnam(const char *name) -{ - struct winbindd_response response; - struct winbindd_request request; - NSS_STATUS ret; - struct passwd *pwd; - - if (*name == WB_AIX_ENCODED) { - return wb_aix_getpwuid(decode_id(name)); - } - - logit("getpwnam '%s'\n", name); - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - STRCPY_RETNULL(request.data.username, name); - - ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); - - HANDLE_ERRORS(ret); - - pwd = fill_pwent(&response.data.pw); - - winbindd_free_response(&response); - - logit("getpwnam gave ptr %p\n", pwd); - - return pwd; -} - -/* - list users -*/ -static int wb_aix_lsuser(char *attributes[], attrval_t results[], int size) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - int len; - char *s; - - if (size != 1 || strcmp(attributes[0], S_USERS) != 0) { - logit("invalid lsuser op\n"); - errno = EINVAL; - return -1; - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - ret = winbindd_request_response(WINBINDD_LIST_USERS, &request, &response); - if (ret != 0) { - errno = EINVAL; - return -1; - } - - len = strlen(response.extra_data.data); - - s = malloc(len+2); - if (!s) { - winbindd_free_response(&response); - errno = ENOMEM; - return -1; - } - - memcpy(s, response.extra_data.data, len+1); - - replace_commas(s); - - results[0].attr_un.au_char = s; - results[0].attr_flag = 0; - - winbindd_free_response(&response); - - return 0; -} - - -/* - list groups -*/ -static int wb_aix_lsgroup(char *attributes[], attrval_t results[], int size) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - int len; - char *s; - - if (size != 1 || strcmp(attributes[0], S_GROUPS) != 0) { - logit("invalid lsgroup op\n"); - errno = EINVAL; - return -1; - } - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - ret = winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response); - if (ret != 0) { - errno = EINVAL; - return -1; - } - - len = strlen(response.extra_data.data); - - s = malloc(len+2); - if (!s) { - winbindd_free_response(&response); - errno = ENOMEM; - return -1; - } - - memcpy(s, response.extra_data.data, len+1); - - replace_commas(s); - - results[0].attr_un.au_char = s; - results[0].attr_flag = 0; - - winbindd_free_response(&response); - - return 0; -} - - -static attrval_t pwd_to_group(struct passwd *pwd) -{ - attrval_t r; - struct group *grp = wb_aix_getgrgid(pwd->pw_gid); - - if (!grp) { - r.attr_flag = EINVAL; - } else { - r.attr_flag = 0; - r.attr_un.au_char = strdup(grp->gr_name); - free_grp(grp); - } - - return r; -} - -static attrval_t pwd_to_groupsids(struct passwd *pwd) -{ - attrval_t r; - char *s, *p; - - if ( (s = wb_aix_getgrset(pwd->pw_name)) == NULL ) { - r.attr_flag = EINVAL; - return r; - } - - if ( (p = malloc(strlen(s)+2)) == NULL ) { - r.attr_flag = ENOMEM; - return r; - } - - strcpy(p, s); - replace_commas(p); - free(s); - - r.attr_un.au_char = p; - - return r; -} - -static attrval_t pwd_to_sid(struct passwd *pwd) -{ - struct winbindd_request request; - struct winbindd_response response; - attrval_t r; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.uid = pwd->pw_uid; - - if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) { - r.attr_flag = ENOENT; - } else { - r.attr_flag = 0; - r.attr_un.au_char = strdup(response.data.sid.sid); - } - - return r; -} - -static int wb_aix_user_attrib(const char *key, char *attributes[], - attrval_t results[], int size) -{ - struct passwd *pwd; - int i; - - pwd = wb_aix_getpwnam(key); - if (!pwd) { - errno = ENOENT; - return -1; - } - - for (i=0;ipw_uid; -#ifdef _AIXVERSION_530 - } else if (strcmp(attributes[i], S_PGID) == 0) { - results[i].attr_un.au_int = pwd->pw_gid; -#endif - } else if (strcmp(attributes[i], S_PWD) == 0) { - results[i].attr_un.au_char = strdup(pwd->pw_passwd); - } else if (strcmp(attributes[i], S_HOME) == 0) { - results[i].attr_un.au_char = strdup(pwd->pw_dir); - } else if (strcmp(attributes[i], S_SHELL) == 0) { - results[i].attr_un.au_char = strdup(pwd->pw_shell); - } else if (strcmp(attributes[i], S_REGISTRY) == 0) { - results[i].attr_un.au_char = strdup("WINBIND"); - } else if (strcmp(attributes[i], S_GECOS) == 0) { - results[i].attr_un.au_char = strdup(pwd->pw_gecos); - } else if (strcmp(attributes[i], S_PGRP) == 0) { - results[i] = pwd_to_group(pwd); - } else if (strcmp(attributes[i], S_GROUPS) == 0) { - results[i] = pwd_to_groupsids(pwd); - } else if (strcmp(attributes[i], "SID") == 0) { - results[i] = pwd_to_sid(pwd); - } else { - logit("Unknown user attribute '%s'\n", attributes[i]); - results[i].attr_flag = EINVAL; - } - } - - free_pwd(pwd); - - return 0; -} - -static int wb_aix_group_attrib(const char *key, char *attributes[], - attrval_t results[], int size) -{ - struct group *grp; - int i; - - grp = wb_aix_getgrnam(key); - if (!grp) { - errno = ENOENT; - return -1; - } - - for (i=0;igr_passwd); - } else if (strcmp(attributes[i], S_ID) == 0) { - results[i].attr_un.au_int = grp->gr_gid; - } else { - logit("Unknown group attribute '%s'\n", attributes[i]); - results[i].attr_flag = EINVAL; - } - } - - free_grp(grp); - - return 0; -} - - -/* - called for user/group enumerations -*/ -static int wb_aix_getentry(char *key, char *table, char *attributes[], - attrval_t results[], int size) -{ - logit("Got getentry with key='%s' table='%s' size=%d attributes[0]='%s'\n", - key, table, size, attributes[0]); - - if (strcmp(key, "ALL") == 0 && - strcmp(table, "user") == 0) { - return wb_aix_lsuser(attributes, results, size); - } - - if (strcmp(key, "ALL") == 0 && - strcmp(table, "group") == 0) { - return wb_aix_lsgroup(attributes, results, size); - } - - if (strcmp(table, "user") == 0) { - return wb_aix_user_attrib(key, attributes, results, size); - } - - if (strcmp(table, "group") == 0) { - return wb_aix_group_attrib(key, attributes, results, size); - } - - logit("Unknown getentry operation key='%s' table='%s'\n", key, table); - - errno = ENOSYS; - return -1; -} - - - -/* - called to start the backend -*/ -static void *wb_aix_open(const char *name, const char *domain, int mode, char *options) -{ - if (strstr(options, "debug")) { - debug_enabled = 1; - } - logit("open name='%s' mode=%d domain='%s' options='%s'\n", name, domain, - mode, options); - return NULL; -} - -static void wb_aix_close(void *token) -{ - logit("close\n"); - return; -} - -#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST -/* - return a list of additional attributes supported by the backend -*/ -static attrlist_t **wb_aix_attrlist(void) -{ - /* pretty confusing but we are allocating the array of pointers - and the structures we'll be pointing to all at once. So - you need N+1 pointers and N structures. */ - - attrlist_t **ret = NULL; - attrlist_t *offset = NULL; - int i; - int n; - size_t size; - - struct attr_types { - const char *name; - int flags; - int type; - } attr_list[] = { - /* user attributes */ - {S_ID, AL_USERATTR, SEC_INT}, - {S_PGRP, AL_USERATTR, SEC_CHAR}, - {S_HOME, AL_USERATTR, SEC_CHAR}, - {S_SHELL, AL_USERATTR, SEC_CHAR}, -#ifdef _AIXVERSION_530 - {S_PGID, AL_USERATTR, SEC_INT}, -#endif - {S_GECOS, AL_USERATTR, SEC_CHAR}, - {S_SHELL, AL_USERATTR, SEC_CHAR}, - {S_PGRP, AL_USERATTR, SEC_CHAR}, - {S_GROUPS, AL_USERATTR, SEC_LIST}, - {"SID", AL_USERATTR, SEC_CHAR}, - - /* group attributes */ - {S_ID, AL_GROUPATTR, SEC_INT} - }; - - logit("method attrlist called\n"); - - n = sizeof(attr_list) / sizeof(struct attr_types); - size = (n*sizeof(attrlist_t *)); - - if ( (ret = malloc( size )) == NULL ) { - errno = ENOMEM; - return NULL; - } - - /* offset to where the structures start in the buffer */ - - offset = (attrlist_t *)(ret + n); - - /* now loop over the user_attr_list[] array and add - all the members */ - - for ( i=0; ial_name = strdup(attr_list[i].name); - a->al_flags = attr_list[i].flags; - a->al_type = attr_list[i].type; - - ret[i] = a; - } - ret[n] = NULL; - - return ret; -} -#endif - - -/* - turn a long username into a short one. Needed to cope with the 8 char - username limit in AIX 5.2 and below -*/ -static int wb_aix_normalize(char *longname, char *shortname) -{ - struct passwd *pwd; - - logit("normalize '%s'\n", longname); - - /* automatically cope with AIX 5.3 with longer usernames - when it comes out */ - if (S_NAMELEN > strlen(longname)) { - strcpy(shortname, longname); - return 1; - } - - pwd = wb_aix_getpwnam(longname); - if (!pwd) { - errno = ENOENT; - return 0; - } - - sprintf(shortname, "%c%07u", WB_AIX_ENCODED, pwd->pw_uid); - - free_pwd(pwd); - - return 1; -} - - -/* - authenticate a user - */ -static int wb_aix_authenticate(char *user, char *pass, - int *reenter, char **message) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *r_user = user; - - logit("authenticate '%s' response='%s'\n", user, pass); - - *reenter = 0; - *message = NULL; - - /* Send off request */ - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (*user == WB_AIX_ENCODED) { - r_user = decode_user(r_user); - if (!r_user) { - return AUTH_NOTFOUND; - } - } - - STRCPY_RET(request.data.auth.user, r_user); - STRCPY_RET(request.data.auth.pass, pass); - - if (*user == WB_AIX_ENCODED) { - free(r_user); - } - - result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); - - winbindd_free_response(&response); - - logit("auth result %d for '%s'\n", result, user); - - if (result == NSS_STATUS_SUCCESS) { - errno = 0; - return AUTH_SUCCESS; - } - - return AUTH_FAILURE; -} - - -/* - change a user password -*/ -static int wb_aix_chpass(char *user, char *oldpass, char *newpass, char **message) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *r_user = user; - - if (*user == WB_AIX_ENCODED) { - r_user = decode_user(r_user); - if (!r_user) { - errno = ENOENT; - return -1; - } - } - - logit("chpass '%s' old='%s' new='%s'\n", r_user, oldpass, newpass); - - *message = NULL; - - /* Send off request */ - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - STRCPY_RET(request.data.chauthtok.user, r_user); - STRCPY_RET(request.data.chauthtok.oldpass, oldpass); - STRCPY_RET(request.data.chauthtok.newpass, newpass); - - if (*user == WB_AIX_ENCODED) { - free(r_user); - } - - result = winbindd_request_response(WINBINDD_PAM_CHAUTHTOK, &request, &response); - - winbindd_free_response(&response); - - if (result == NSS_STATUS_SUCCESS) { - errno = 0; - return 0; - } - - errno = EINVAL; - return -1; -} - -/* - don't do any password strength testing for now -*/ -static int wb_aix_passwdrestrictions(char *user, char *newpass, char *oldpass, - char **message) -{ - logit("passwdresrictions called for '%s'\n", user); - return 0; -} - - -static int wb_aix_passwdexpired(char *user, char **message) -{ - logit("passwdexpired '%s'\n", user); - /* we should check the account bits here */ - return 0; -} - - -/* - we can't return a crypt() password -*/ -static char *wb_aix_getpasswd(char *user) -{ - logit("getpasswd '%s'\n", user); - errno = ENOSYS; - return NULL; -} - -/* - this is called to update things like the last login time. We don't - currently pass this onto the DC -*/ -static int wb_aix_putentry(char *key, char *table, char *attributes[], - attrval_t values[], int size) -{ - logit("putentry key='%s' table='%s' attrib='%s'\n", - key, table, size>=1?attributes[0]:""); - errno = ENOSYS; - return -1; -} - -static int wb_aix_commit(char *key, char *table) -{ - logit("commit key='%s' table='%s'\n"); - errno = ENOSYS; - return -1; -} - -static int wb_aix_getgrusers(char *group, void *result, int type, int *size) -{ - logit("getgrusers group='%s'\n", group); - errno = ENOSYS; - return -1; -} - - -#define DECL_METHOD(x) \ -int method_ ## x(void) \ -{ \ - logit("UNIMPLEMENTED METHOD '%s'\n", #x); \ - errno = EINVAL; \ - return -1; \ -} - -#if LOG_UNIMPLEMENTED_CALLS -DECL_METHOD(delgroup); -DECL_METHOD(deluser); -DECL_METHOD(newgroup); -DECL_METHOD(newuser); -DECL_METHOD(putgrent); -DECL_METHOD(putgrusers); -DECL_METHOD(putpwent); -DECL_METHOD(lock); -DECL_METHOD(unlock); -DECL_METHOD(getcred); -DECL_METHOD(setcred); -DECL_METHOD(deletecred); -#endif - -int wb_aix_init(struct secmethod_table *methods) -{ - ZERO_STRUCTP(methods); - -#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_VERSION - methods->method_version = SECMETHOD_VERSION_520; -#endif - - methods->method_getgrgid = wb_aix_getgrgid; - methods->method_getgrnam = wb_aix_getgrnam; - methods->method_getgrset = wb_aix_getgrset; - methods->method_getpwnam = wb_aix_getpwnam; - methods->method_getpwuid = wb_aix_getpwuid; - methods->method_getentry = wb_aix_getentry; - methods->method_open = wb_aix_open; - methods->method_close = wb_aix_close; - methods->method_normalize = wb_aix_normalize; - methods->method_passwdexpired = wb_aix_passwdexpired; - methods->method_putentry = wb_aix_putentry; - methods->method_getpasswd = wb_aix_getpasswd; - methods->method_authenticate = wb_aix_authenticate; - methods->method_commit = wb_aix_commit; - methods->method_chpass = wb_aix_chpass; - methods->method_passwdrestrictions = wb_aix_passwdrestrictions; - methods->method_getgracct = wb_aix_getgracct; - methods->method_getgrusers = wb_aix_getgrusers; -#ifdef HAVE_STRUCT_SECMETHOD_TABLE_METHOD_ATTRLIST - methods->method_attrlist = wb_aix_attrlist; -#endif - -#if LOG_UNIMPLEMENTED_CALLS - methods->method_delgroup = method_delgroup; - methods->method_deluser = method_deluser; - methods->method_newgroup = method_newgroup; - methods->method_newuser = method_newuser; - methods->method_putgrent = method_putgrent; - methods->method_putgrusers = method_putgrusers; - methods->method_putpwent = method_putpwent; - methods->method_lock = method_lock; - methods->method_unlock = method_unlock; - methods->method_getcred = method_getcred; - methods->method_setcred = method_setcred; - methods->method_deletecred = method_deletecred; -#endif - - return AUTH_SUCCESS; -} - diff --git a/source3/nsswitch/winbind_nss_config.h b/source3/nsswitch/winbind_nss_config.h deleted file mode 100644 index bed507fdeb..0000000000 --- a/source3/nsswitch/winbind_nss_config.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_CONFIG_H -#define _WINBIND_NSS_CONFIG_H - -/* shutup the compiler warnings due to krb5.h on 64-bit sles9 */ -#ifdef SIZEOF_LONG -#undef SIZEOF_LONG -#endif - -/* - * we don't need socket wrapper - * nor nss wrapper here and we don't - * want to depend on swrap_close() - * so we better disable both - */ -#define SOCKET_WRAPPER_NOT_REPLACE -#define NSS_WRAPPER_NOT_REPLACE - -/* Include header files from data in config.h file */ - -#ifndef NO_CONFIG_H -#include "../replace/replace.h" -#endif - -#include "system/filesys.h" -#include "system/network.h" -#include "system/passwd.h" - -#include "nsswitch/winbind_nss.h" - -/* I'm trying really hard not to include anything from smb.h with the - result of some silly looking redeclaration of structures. */ - -#ifndef FSTRING_LEN -#define FSTRING_LEN 256 -typedef char fstring[FSTRING_LEN]; -#endif - -/* Some systems (SCO) treat UNIX domain sockets as FIFOs */ - -#ifndef S_IFSOCK -#define S_IFSOCK S_IFIFO -#endif - -#ifndef S_ISSOCK -#define S_ISSOCK(mode) ((mode & S_IFSOCK) == S_IFSOCK) -#endif - -#endif diff --git a/source3/nsswitch/winbind_nss_freebsd.c b/source3/nsswitch/winbind_nss_freebsd.c deleted file mode 100644 index 02e29f3131..0000000000 --- a/source3/nsswitch/winbind_nss_freebsd.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - AIX loadable authentication module, providing identification - routines against Samba winbind/Windows NT Domain - - Copyright (C) Aaron Collins 2003 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "winbind_client.h" - -/* Make sure that the module gets registered needed by freebsd 5.1 */ - -extern enum nss_status _nss_winbind_getgrent_r(struct group *, char *, size_t, - int *); -extern enum nss_status _nss_winbind_getgrnam_r(const char *, struct group *, - char *, size_t, int *); -extern enum nss_status _nss_winbind_getgrgid_r(gid_t gid, struct group *, char *, - size_t, int *); -extern enum nss_status _nss_winbind_setgrent(void); -extern enum nss_status _nss_winbind_endgrent(void); - -extern enum nss_status _nss_winbind_getpwent_r(struct passwd *, char *, size_t, - int *); -extern enum nss_status _nss_winbind_getpwnam_r(const char *, struct passwd *, - char *, size_t, int *); -extern enum nss_status _nss_winbind_getpwuid_r(gid_t gid, struct passwd *, char *, - size_t, int *); -extern enum nss_status _nss_winbind_setpwent(void); -extern enum nss_status _nss_winbind_endpwent(void); - -NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r); -NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r); -NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r); -NSS_METHOD_PROTOTYPE(__nss_compat_setgrent); -NSS_METHOD_PROTOTYPE(__nss_compat_endgrent); - -NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r); -NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r); -NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r); -NSS_METHOD_PROTOTYPE(__nss_compat_setpwent); -NSS_METHOD_PROTOTYPE(__nss_compat_endpwent); - -static ns_mtab methods[] = { -{ NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_winbind_getgrnam_r }, -{ NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_winbind_getgrgid_r }, -{ NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_winbind_getgrent_r }, -{ NSDB_GROUP, "endgrent", __nss_compat_setgrent, _nss_winbind_setgrent }, -{ NSDB_GROUP, "setgrent", __nss_compat_endgrent, _nss_winbind_endgrent }, - -{ NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_winbind_getpwnam_r }, -{ NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_winbind_getpwuid_r }, -{ NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_winbind_getpwent_r }, -{ NSDB_PASSWD, "endpwent", __nss_compat_setpwent, _nss_winbind_setpwent }, -{ NSDB_PASSWD, "setpwent", __nss_compat_endpwent, _nss_winbind_endpwent }, - -}; - -ns_mtab * -nss_module_register(const char *source, unsigned int *mtabsize, - nss_module_unregister_fn *unreg) -{ - *mtabsize = sizeof(methods)/sizeof(methods[0]); - *unreg = NULL; - return (methods); -} diff --git a/source3/nsswitch/winbind_nss_hpux.h b/source3/nsswitch/winbind_nss_hpux.h deleted file mode 100644 index 62cf3c26c5..0000000000 --- a/source3/nsswitch/winbind_nss_hpux.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Donated by HP to enable Winbindd to build on HPUX 11.x. - Copyright (C) Jeremy Allison 2002. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#ifndef _WINBIND_NSS_HPUX_H -#define _WINBIND_NSS_HPUX_H - -#include - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -#ifdef HAVE_SYNCH_H -#include -#endif -#ifdef HAVE_PTHREAD_H -#include -#endif - -typedef enum { - NSS_SUCCESS, - NSS_NOTFOUND, - NSS_UNAVAIL, - NSS_TRYAGAIN -} nss_status_t; - -typedef nss_status_t NSS_STATUS; - -struct nss_backend; - -typedef nss_status_t (*nss_backend_op_t)(struct nss_backend *, void *args); - -struct nss_backend { - nss_backend_op_t *ops; - int n_ops; -}; -typedef struct nss_backend nss_backend_t; -typedef int nss_dbop_t; - -#include -#include -#include - -#ifndef NSS_INCLUDE_UNSAFE -#define NSS_INCLUDE_UNSAFE 1 /* Build old, MT-unsafe interfaces, */ -#endif /* NSS_INCLUDE_UNSAFE */ - -enum nss_netgr_argn { - NSS_NETGR_MACHINE, - NSS_NETGR_USER, - NSS_NETGR_DOMAIN, - NSS_NETGR_N -}; - -enum nss_netgr_status { - NSS_NETGR_FOUND, - NSS_NETGR_NO, - NSS_NETGR_NOMEM -}; - -typedef unsigned nss_innetgr_argc; -typedef char **nss_innetgr_argv; - -struct nss_innetgr_1arg { - nss_innetgr_argc argc; - nss_innetgr_argv argv; -}; - -typedef struct { - void *result; /* "result" parameter to getXbyY_r() */ - char *buffer; /* "buffer" " " */ - int buflen; /* "buflen" " " */ -} nss_XbyY_buf_t; - -extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size); -extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *); - -union nss_XbyY_key { - uid_t uid; - gid_t gid; - const char *name; - int number; - struct { - long net; - int type; - } netaddr; - struct { - const char *addr; - int len; - int type; - } hostaddr; - struct { - union { - const char *name; - int port; - } serv; - const char *proto; - } serv; - void *ether; -}; - -typedef struct nss_XbyY_args { - nss_XbyY_buf_t buf; - int stayopen; - /* - * Support for setXXXent(stayopen) - * Used only in hosts, protocols, - * networks, rpc, and services. - */ - int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen); - union nss_XbyY_key key; - - void *returnval; - int erange; - int h_errno; - nss_status_t status; -} nss_XbyY_args_t; - -#endif /* _WINBIND_NSS_HPUX_H */ diff --git a/source3/nsswitch/winbind_nss_irix.c b/source3/nsswitch/winbind_nss_irix.c deleted file mode 100644 index 5bc0fa54da..0000000000 --- a/source3/nsswitch/winbind_nss_irix.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Windows NT Domain nsswitch module - - Copyright (C) Tim Potter 2000 - Copyright (C) James Peach 2006 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "winbind_client.h" - -#ifndef PRINTF_ATTRIBUTE -#define PRINTF_ATTRIBUTE(m, n) -#endif - -#ifndef HAVE_ASPRINTF_DECL -/*PRINTFLIKE2 */ -int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); -#endif - -#ifdef HAVE_NS_API_H -#undef STATIC -#undef DYNAMIC -#include -#endif - -/* Maximum number of users to pass back over the unix domain socket - per call. This is not a static limit on the total number of users - or groups returned in total. */ - -#define MAX_GETPWENT_USERS 250 -#define MAX_GETGRENT_USERS 250 - -/* Prototypes from wb_common.c */ - -extern int winbindd_fd; - -#ifdef HAVE_NS_API_H - -/* IRIX version */ - -static int send_next_request(nsd_file_t *, struct winbindd_request *); -static int do_list(int state, nsd_file_t *rq); - -static nsd_file_t *current_rq = NULL; -static int current_winbind_xid = 0; -static int next_winbind_xid = 0; - -typedef struct winbind_xid { - int xid; - nsd_file_t *rq; - struct winbindd_request *request; - struct winbind_xid *next; -} winbind_xid_t; - -static winbind_xid_t *winbind_xids = (winbind_xid_t *)0; - -static int -winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request) -{ - winbind_xid_t *new; - - nsd_logprintf(NSD_LOG_LOW, - "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n", - xid, rq, request); - new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t)); - if (!new) { - nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n"); - return NSD_ERROR; - } - - new->xid = xid; - new->rq = rq; - new->request = request; - new->next = winbind_xids; - winbind_xids = new; - - return NSD_CONTINUE; -} - -/* -** This routine will look down the xid list and return the request -** associated with an xid. We remove the record if it is found. -*/ -nsd_file_t * -winbind_xid_lookup(int xid, struct winbindd_request **requestp) -{ - winbind_xid_t **last, *dx; - nsd_file_t *result=0; - - for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid); - last = &dx->next, dx = dx->next); - if (dx) { - *last = dx->next; - result = dx->rq; - *requestp = dx->request; - SAFE_FREE(dx); - } - nsd_logprintf(NSD_LOG_LOW, - "entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x\n", - xid, result, dx->request); - - return result; -} - -static int -winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to) -{ - nsd_file_t *rq; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n"); - rq = to->t_file; - *rqp = rq; - nsd_timeout_remove(rq); - request = to->t_clientdata; - return(send_next_request(rq, request)); -} - -static void -dequeue_request(void) -{ - nsd_file_t *rq; - struct winbindd_request *request; - - /* - * Check for queued requests - */ - if (winbind_xids) { - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind) unqueue xid %d\n", - current_winbind_xid); - rq = winbind_xid_lookup(current_winbind_xid++, &request); - /* cause a timeout on the queued request so we can send it */ - nsd_timeout_new(rq,1,winbind_startnext_timeout,request); - } -} - -static int -do_request(nsd_file_t *rq, struct winbindd_request *request) -{ - if (winbind_xids == NULL) { - /* - * No outstanding requests. - * Send off the request to winbindd - */ - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) sending request\n"); - return(send_next_request(rq, request)); - } else { - /* - * Just queue it up for now - previous callout or timout - * will start it up - */ - nsd_logprintf(NSD_LOG_MIN, - "lookup (winbind): queue request xid = %d\n", - next_winbind_xid); - return(winbind_xid_new(next_winbind_xid++, rq, request)); - } -} - -static int -winbind_callback(nsd_file_t **rqp, int fd) -{ - struct winbindd_response response; - nsd_file_t *rq; - NSS_STATUS status; - char * result = NULL; - size_t rlen; - - dequeue_request(); - - nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n"); - - rq = current_rq; - *rqp = rq; - - nsd_timeout_remove(rq); - nsd_callback_remove(fd); - - ZERO_STRUCT(response); - status = winbindd_get_response(&response); - - if (status != NSS_STATUS_SUCCESS) { - /* free any extra data area in response structure */ - winbindd_free_response(&response); - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) returning not found, status = %d\n", - status); - - switch (status) { - case NSS_STATUS_UNAVAIL: - rq->f_status = NS_UNAVAIL; - break; - case NSS_STATUS_TRYAGAIN: - rq->f_status = NS_TRYAGAIN; - break; - case NSS_STATUS_NOTFOUND: - /* FALLTHRU */ - default: - rq->f_status = NS_NOTFOUND; - } - - return NSD_NEXT; - } - - switch ((int)rq->f_cmd_data) { - case WINBINDD_WINS_BYNAME: - case WINBINDD_WINS_BYIP: - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) WINS_BYNAME | WINS_BYIP\n"); - - rlen = asprintf(&result, "%s\n", response.data.winsresp); - if (rlen == 0 || result == NULL) { - return NSD_ERROR; - } - - winbindd_free_response(&response); - - nsd_logprintf(NSD_LOG_MIN, " %s\n", result); - nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC); - return NSD_OK; - - case WINBINDD_GETPWUID: - case WINBINDD_GETPWNAM: - { - struct winbindd_pw *pw = &response.data.pw; - - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) GETPWUID | GETPWUID\n"); - - rlen = asprintf(&result,"%s:%s:%d:%d:%s:%s:%s\n", - pw->pw_name, - pw->pw_passwd, - pw->pw_uid, - pw->pw_gid, - pw->pw_gecos, - pw->pw_dir, - pw->pw_shell); - if (rlen == 0 || result == NULL) - return NSD_ERROR; - - winbindd_free_response(&response); - - nsd_logprintf(NSD_LOG_MIN, " %s\n", result); - nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC); - return NSD_OK; - } - - case WINBINDD_GETGRNAM: - case WINBINDD_GETGRGID: - { - const struct winbindd_gr *gr = &response.data.gr; - const char * members; - - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) GETGRNAM | GETGRGID\n"); - - if (gr->num_gr_mem && response.extra_data.data) { - members = response.extra_data.data; - } else { - members = ""; - } - - rlen = asprintf(&result, "%s:%s:%d:%s\n", - gr->gr_name, gr->gr_passwd, gr->gr_gid, members); - if (rlen == 0 || result == NULL) - return NSD_ERROR; - - winbindd_free_response(&response); - - nsd_logprintf(NSD_LOG_MIN, " %s\n", result); - nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC); - return NSD_OK; - } - - case WINBINDD_SETGRENT: - case WINBINDD_SETPWENT: - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) SETGRENT | SETPWENT\n"); - winbindd_free_response(&response); - return(do_list(1,rq)); - - case WINBINDD_GETGRENT: - case WINBINDD_GETGRLST: - { - int entries; - - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) GETGRENT | GETGRLIST %d responses\n", - response.data.num_entries); - - if (response.data.num_entries) { - const struct winbindd_gr *gr = &response.data.gr; - const char * members; - fstring grp_name; - int i; - - gr = (struct winbindd_gr *)response.extra_data.data; - if (! gr ) { - nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); - winbindd_free_response(&response); - return NSD_ERROR; - } - - members = (char *)response.extra_data.data + - (response.data.num_entries * sizeof(struct winbindd_gr)); - - for (i = 0; i < response.data.num_entries; i++) { - snprintf(grp_name, sizeof(grp_name) - 1, "%s:%s:%d:", - gr->gr_name, gr->gr_passwd, gr->gr_gid); - - nsd_append_element(rq, NS_SUCCESS, result, rlen); - nsd_append_result(rq, NS_SUCCESS, - &members[gr->gr_mem_ofs], - strlen(&members[gr->gr_mem_ofs])); - - /* Don't log the whole list, because it might be - * _really_ long and we probably don't want to clobber - * the log with it. - */ - nsd_logprintf(NSD_LOG_MIN, " %s (...)\n", grp_name); - - gr++; - } - } - - entries = response.data.num_entries; - winbindd_free_response(&response); - if (entries < MAX_GETPWENT_USERS) - return(do_list(2,rq)); - else - return(do_list(1,rq)); - } - - case WINBINDD_GETPWENT: - { - int entries; - - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) GETPWENT %d responses\n", - response.data.num_entries); - - if (response.data.num_entries) { - struct winbindd_pw *pw = &response.data.pw; - int i; - - pw = (struct winbindd_pw *)response.extra_data.data; - if (! pw ) { - nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); - winbindd_free_response(&response); - return NSD_ERROR; - } - for (i = 0; i < response.data.num_entries; i++) { - result = NULL; - rlen = asprintf(&result, "%s:%s:%d:%d:%s:%s:%s", - pw->pw_name, - pw->pw_passwd, - pw->pw_uid, - pw->pw_gid, - pw->pw_gecos, - pw->pw_dir, - pw->pw_shell); - - if (rlen != 0 && result != NULL) { - nsd_logprintf(NSD_LOG_MIN, " %s\n",result); - nsd_append_element(rq, NS_SUCCESS, result, rlen); - free(result); - } - - pw++; - } - } - - entries = response.data.num_entries; - winbindd_free_response(&response); - if (entries < MAX_GETPWENT_USERS) - return(do_list(2,rq)); - else - return(do_list(1,rq)); - } - - case WINBINDD_ENDGRENT: - case WINBINDD_ENDPWENT: - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) ENDGRENT | ENDPWENT\n"); - nsd_append_element(rq, NS_SUCCESS, "\n", 1); - winbindd_free_response(&response); - return NSD_NEXT; - - default: - winbindd_free_response(&response); - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) invalid command %d\n", (int)rq->f_cmd_data); - return NSD_NEXT; - } -} - -static int -winbind_timeout(nsd_file_t **rqp, nsd_times_t *to) -{ - nsd_file_t *rq; - - dequeue_request(); - - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n"); - - rq = to->t_file; - *rqp = rq; - - /* Remove the callback and timeout */ - nsd_callback_remove(winbindd_fd); - nsd_timeout_remove(rq); - - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; -} - -static int -send_next_request(nsd_file_t *rq, struct winbindd_request *request) -{ - NSS_STATUS status; - long timeout; - - switch (rq->f_index) { - case LOOKUP: - timeout = nsd_attr_fetch_long(rq->f_attrs, - "lookup_timeout", 10, 10); - break; - case LIST: - timeout = nsd_attr_fetch_long(rq->f_attrs, - "list_timeout", 10, 10); - break; - default: - nsd_logprintf(NSD_LOG_OPER, - "send_next_request (winbind) " - "invalid request type %d\n", rq->f_index); - rq->f_status = NS_BADREQ; - return NSD_NEXT; - } - - nsd_logprintf(NSD_LOG_MIN, - "send_next_request (winbind) %d, timeout = %d sec\n", - rq->f_cmd_data, timeout); - status = winbindd_send_request((int)rq->f_cmd_data,0,request); - SAFE_FREE(request); - - if (status != NSS_STATUS_SUCCESS) { - nsd_logprintf(NSD_LOG_MIN, - "send_next_request (winbind) error status = %d\n", - status); - rq->f_status = status; - return NSD_NEXT; - } - - current_rq = rq; - - /* - * Set up callback and timeouts - */ - nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n", - winbindd_fd); - - nsd_callback_new(winbindd_fd, winbind_callback, NSD_READ); - nsd_timeout_new(rq, timeout * 1000, winbind_timeout, NULL); - return NSD_CONTINUE; -} - -int init(void) -{ - nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n"); - return(NSD_OK); -} - -int lookup(nsd_file_t *rq) -{ - char *map; - char *key; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); - if (! map || ! key) { - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n"); - rq->f_status = NS_BADREQ; - return NSD_ERROR; - } - - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map); - - request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); - if (! request) { - nsd_logprintf(NSD_LOG_RESOURCE, - "lookup (winbind): failed malloc\n"); - return NSD_ERROR; - } - - if (strcasecmp(map,"passwd.byuid") == 0) { - request->data.uid = atoi(key); - rq->f_cmd_data = (void *)WINBINDD_GETPWUID; - } else if (strcasecmp(map,"passwd.byname") == 0) { - strncpy(request->data.username, key, - sizeof(request->data.username) - 1); - request->data.username[sizeof(request->data.username) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_GETPWNAM; - } else if (strcasecmp(map,"group.byname") == 0) { - strncpy(request->data.groupname, key, - sizeof(request->data.groupname) - 1); - request->data.groupname[sizeof(request->data.groupname) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_GETGRNAM; - } else if (strcasecmp(map,"group.bygid") == 0) { - request->data.gid = atoi(key); - rq->f_cmd_data = (void *)WINBINDD_GETGRGID; - } else if (strcasecmp(map,"hosts.byname") == 0) { - strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); - request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME; - } else if (strcasecmp(map,"hosts.byaddr") == 0) { - strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); - request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP; - } else { - /* - * Don't understand this map - just return not found - */ - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - return(do_request(rq, request)); -} - -int list(nsd_file_t *rq) -{ - char *map; - - nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - if (! map ) { - nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n"); - rq->f_status = NS_BADREQ; - return NSD_ERROR; - } - - nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map); - - return (do_list(0,rq)); -} - -static int -do_list(int state, nsd_file_t *rq) -{ - char *map; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state); - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); - if (! request) { - nsd_logprintf(NSD_LOG_RESOURCE, - "do_list (winbind): failed malloc\n"); - return NSD_ERROR; - } - - if (strcasecmp(map,"passwd.byname") == 0) { - switch (state) { - case 0: - rq->f_cmd_data = (void *)WINBINDD_SETPWENT; - break; - case 1: - request->data.num_entries = MAX_GETPWENT_USERS; - rq->f_cmd_data = (void *)WINBINDD_GETPWENT; - break; - case 2: - rq->f_cmd_data = (void *)WINBINDD_ENDPWENT; - break; - default: - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - } else if (strcasecmp(map,"group.byname") == 0) { - switch (state) { - case 0: - rq->f_cmd_data = (void *)WINBINDD_SETGRENT; - break; - case 1: - request->data.num_entries = MAX_GETGRENT_USERS; - rq->f_cmd_data = (void *)WINBINDD_GETGRENT; - break; - case 2: - rq->f_cmd_data = (void *)WINBINDD_ENDGRENT; - break; - default: - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - } else { - /* - * Don't understand this map - just return not found - */ - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - return(do_request(rq, request)); -} - -#endif /* HAVE_NS_API_H */ diff --git a/source3/nsswitch/winbind_nss_irix.h b/source3/nsswitch/winbind_nss_irix.h deleted file mode 100644 index b40b14b0b0..0000000000 --- a/source3/nsswitch/winbind_nss_irix.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_IRIX_H -#define _WINBIND_NSS_IRIX_H - -/* following required to prevent warnings of double definition - * of datum from ns_api.h -*/ -#ifdef DATUM -#define _DATUM_DEFINED -#endif - -#include - -typedef enum -{ - NSS_STATUS_SUCCESS=NS_SUCCESS, - NSS_STATUS_NOTFOUND=NS_NOTFOUND, - NSS_STATUS_UNAVAIL=NS_UNAVAIL, - NSS_STATUS_TRYAGAIN=NS_TRYAGAIN -} NSS_STATUS; - -#endif /* _WINBIND_NSS_IRIX_H */ diff --git a/source3/nsswitch/winbind_nss_linux.c b/source3/nsswitch/winbind_nss_linux.c deleted file mode 100644 index c11c18759e..0000000000 --- a/source3/nsswitch/winbind_nss_linux.c +++ /dev/null @@ -1,1477 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Windows NT Domain nsswitch module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "winbind_client.h" - -#if HAVE_PTHREAD_H -#include -#endif - -#if HAVE_PTHREAD -static pthread_mutex_t winbind_nss_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif - -/* Maximum number of users to pass back over the unix domain socket - per call. This is not a static limit on the total number of users - or groups returned in total. */ - -#define MAX_GETPWENT_USERS 250 -#define MAX_GETGRENT_USERS 250 - -NSS_STATUS _nss_winbind_setpwent(void); -NSS_STATUS _nss_winbind_endpwent(void); -NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_setgrent(void); -NSS_STATUS _nss_winbind_endgrent(void); -NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, - long int limit, int *errnop); -NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, - int *num_groups, char *buffer, size_t buf_size, - int *errnop); -NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); -NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); -NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, - size_t buflen, int *errnop); - -/* Prototypes from wb_common.c */ - -/* Allocate some space from the nss static buffer. The buffer and buflen - are the pointers passed in by the C library to the _nss_ntdom_* - functions. */ - -static char *get_static(char **buffer, size_t *buflen, size_t len) -{ - char *result; - - /* Error check. We return false if things aren't set up right, or - there isn't enough buffer space left. */ - - if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { - return NULL; - } - - /* Return an index into the static buffer */ - - result = *buffer; - *buffer += len; - *buflen -= len; - - return result; -} - -/* I've copied the strtok() replacement function next_token_Xalloc() from - lib/util_str.c as I really don't want to have to link in any other - objects if I can possibly avoid it. */ - -static bool next_token_alloc(const char **ptr, - char **pp_buff, - const char *sep) -{ - char *s; - char *saved_s; - char *pbuf; - bool quoted; - size_t len=1; - - *pp_buff = NULL; - if (!ptr) { - return(false); - } - - s = (char *)*ptr; - - /* default to simple separators */ - if (!sep) { - sep = " \t\n\r"; - } - - /* find the first non sep char */ - while (*s && strchr(sep,*s)) { - s++; - } - - /* nothing left? */ - if (!*s) { - return false; - } - - /* When restarting we need to go from here. */ - saved_s = s; - - /* Work out the length needed. */ - for (quoted = false; *s && - (quoted || !strchr(sep,*s)); s++) { - if (*s == '\"') { - quoted = !quoted; - } else { - len++; - } - } - - /* We started with len = 1 so we have space for the nul. */ - *pp_buff = (char *)malloc(len); - if (!*pp_buff) { - return false; - } - - /* copy over the token */ - pbuf = *pp_buff; - s = saved_s; - for (quoted = false; *s && - (quoted || !strchr(sep,*s)); s++) { - if ( *s == '\"' ) { - quoted = !quoted; - } else { - *pbuf++ = *s; - } - } - - *ptr = (*s) ? s+1 : s; - *pbuf = 0; - - return true; -} - -/* Fill a pwent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_pwent(struct passwd *result, - struct winbindd_pw *pw, - char **buffer, size_t *buflen) -{ - /* User name */ - - if ((result->pw_name = - get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_name, pw->pw_name); - - /* Password */ - - if ((result->pw_passwd = - get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_passwd, pw->pw_passwd); - - /* [ug]id */ - - result->pw_uid = pw->pw_uid; - result->pw_gid = pw->pw_gid; - - /* GECOS */ - - if ((result->pw_gecos = - get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_gecos, pw->pw_gecos); - - /* Home directory */ - - if ((result->pw_dir = - get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_dir, pw->pw_dir); - - /* Logon shell */ - - if ((result->pw_shell = - get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_shell, pw->pw_shell); - - /* The struct passwd for Solaris has some extra fields which must - be initialised or nscd crashes. */ - -#if HAVE_PASSWD_PW_COMMENT - result->pw_comment = ""; -#endif - -#if HAVE_PASSWD_PW_AGE - result->pw_age = ""; -#endif - - return NSS_STATUS_SUCCESS; -} - -/* Fill a grent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, - char *gr_mem, char **buffer, size_t *buflen) -{ - char *name; - int i; - char *tst; - - /* Group name */ - - if ((result->gr_name = - get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_name, gr->gr_name); - - /* Password */ - - if ((result->gr_passwd = - get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) { - - /* Out of memory */ - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_passwd, gr->gr_passwd); - - /* gid */ - - result->gr_gid = gr->gr_gid; - - /* Group membership */ - - if ((gr->num_gr_mem < 0) || !gr_mem) { - gr->num_gr_mem = 0; - } - - /* this next value is a pointer to a pointer so let's align it */ - - /* Calculate number of extra bytes needed to align on pointer size boundry */ - if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0) - i = sizeof(char*) - i; - - if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * - sizeof(char *)+i))) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - result->gr_mem = (char **)(tst + i); - - if (gr->num_gr_mem == 0) { - - /* Group is empty */ - - *(result->gr_mem) = NULL; - return NSS_STATUS_SUCCESS; - } - - /* Start looking at extra data */ - - i = 0; - - while(next_token_alloc((const char **)&gr_mem, &name, ",")) { - /* Allocate space for member */ - if (((result->gr_mem)[i] = - get_static(buffer, buflen, strlen(name) + 1)) == NULL) { - free(name); - /* Out of memory */ - return NSS_STATUS_TRYAGAIN; - } - strcpy((result->gr_mem)[i], name); - free(name); - i++; - } - - /* Terminate list */ - - (result->gr_mem)[i] = NULL; - - return NSS_STATUS_SUCCESS; -} - -/* - * NSS user functions - */ - -static struct winbindd_response getpwent_response; - -static int ndx_pw_cache; /* Current index into pwd cache */ -static int num_pw_cache; /* Current size of pwd cache */ - -/* Rewind "file pointer" to start of ntdom password database */ - -NSS_STATUS -_nss_winbind_setpwent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setpwent\n", getpid()); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - winbindd_free_response(&getpwent_response); - } - - ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - return ret; -} - -/* Close ntdom password database "file pointer" */ - -NSS_STATUS -_nss_winbind_endpwent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endpwent\n", getpid()); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - winbindd_free_response(&getpwent_response); - } - - ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* Fetch the next password entry from ntdom password database */ - -NSS_STATUS -_nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - static int called_again; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwent\n", getpid()); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_pw_cache < num_pw_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_pw_cache > 0) { - winbindd_free_response(&getpwent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getpwent_response); - - request.data.num_entries = MAX_GETPWENT_USERS; - - ret = winbindd_request_response(WINBINDD_GETPWENT, &request, - &getpwent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_pw *pw_cache; - - /* Fill cache */ - - ndx_pw_cache = 0; - num_pw_cache = getpwent_response.data.num_entries; - - /* Return a result */ - - return_result: - - pw_cache = (struct winbindd_pw *) - getpwent_response.extra_data.data; - - /* Check data is valid */ - - if (pw_cache == NULL) { - ret = NSS_STATUS_NOTFOUND; - goto done; - } - - ret = fill_pwent(result, &pw_cache[ndx_pw_cache], - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = true; - *errnop = errno = ERANGE; - goto done; - } - - *errnop = errno = 0; - called_again = false; - ndx_pw_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_pw_cache == num_pw_cache) { - ndx_pw_cache = num_pw_cache = 0; - winbindd_free_response(&getpwent_response); - } - } - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - return ret; -} - -/* Return passwd struct from uid */ - -NSS_STATUS -_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwuid_r %d\n", getpid(), (unsigned int)uid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - /* If our static buffer needs to be expanded we are called again */ - if (!keep_response || uid != response.data.pw.pw_uid) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = errno = 0; - } - - winbindd_free_response(&response); - - done: - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(), - (unsigned int)uid, nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* Return passwd struct from username */ -NSS_STATUS -_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwnam_r %s\n", getpid(), name); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response || strcmp(name,response.data.pw.pw_name) != 0) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.username, name, - sizeof(request.data.username) - 1); - request.data.username - [sizeof(request.data.username) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = errno = 0; - } - - winbindd_free_response(&response); - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(), - name, nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* - * NSS group functions - */ - -static struct winbindd_response getgrent_response; - -static int ndx_gr_cache; /* Current index into grp cache */ -static int num_gr_cache; /* Current size of grp cache */ - -/* Rewind "file pointer" to start of ntdom group database */ - -NSS_STATUS -_nss_winbind_setgrent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setgrent\n", getpid()); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - winbindd_free_response(&getgrent_response); - } - - ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* Close "file pointer" for ntdom group database */ - -NSS_STATUS -_nss_winbind_endgrent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endgrent\n", getpid()); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - winbindd_free_response(&getgrent_response); - } - - ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* Get next entry from ntdom group database */ - -static NSS_STATUS -winbind_getgrent(enum winbindd_cmd cmd, - struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_request request; - static int called_again; - - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrent\n", getpid()); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_gr_cache < num_gr_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_gr_cache > 0) { - winbindd_free_response(&getgrent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getgrent_response); - - request.data.num_entries = MAX_GETGRENT_USERS; - - ret = winbindd_request_response(cmd, &request, - &getgrent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_gr *gr_cache; - int mem_ofs; - - /* Fill cache */ - - ndx_gr_cache = 0; - num_gr_cache = getgrent_response.data.num_entries; - - /* Return a result */ - - return_result: - - gr_cache = (struct winbindd_gr *) - getgrent_response.extra_data.data; - - /* Check data is valid */ - - if (gr_cache == NULL) { - ret = NSS_STATUS_NOTFOUND; - goto done; - } - - /* Fill group membership. The offset into the extra data - for the group membership is the reported offset plus the - size of all the winbindd_gr records returned. */ - - mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + - num_gr_cache * sizeof(struct winbindd_gr); - - ret = fill_grent(result, &gr_cache[ndx_gr_cache], - ((char *)getgrent_response.extra_data.data)+mem_ofs, - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = true; - *errnop = errno = ERANGE; - goto done; - } - - *errnop = 0; - called_again = false; - ndx_gr_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_gr_cache == num_gr_cache) { - ndx_gr_cache = num_gr_cache = 0; - winbindd_free_response(&getgrent_response); - } - } - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - - -NSS_STATUS -_nss_winbind_getgrent_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); -} - -NSS_STATUS -_nss_winbind_getgrlst_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); -} - -/* Return group struct from group name */ - -NSS_STATUS -_nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - /* If our static buffer needs to be expanded we are called again */ - /* Or if the stored response group name differs from the request. */ - - if (!keep_response || strcmp(name,response.data.gr.gr_name) != 0) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.groupname, name, - sizeof(request.data.groupname)); - request.data.groupname - [sizeof(request.data.groupname) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = 0; - } - - winbindd_free_response(&response); - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(), - name, nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* Return group struct from gid */ - -NSS_STATUS -_nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - /* If our static buffer needs to be expanded we are called again */ - /* Or if the stored response group name differs from the request. */ - - if (!keep_response || gid != response.data.gr.gr_gid) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.gid = gid; - - ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = 0; - } - - winbindd_free_response(&response); - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(), - (unsigned int)gid, nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - return ret; -} - -/* Initialise supplementary groups */ - -NSS_STATUS -_nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, long int limit, - int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - int i; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), - user, group); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.username, user, - sizeof(request.data.username) - 1); - - ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - int num_gids = response.data.num_entries; - gid_t *gid_list = (gid_t *)response.extra_data.data; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS " - "and %d gids\n", getpid(), - user, num_gids); -#endif - if (gid_list == NULL) { - ret = NSS_STATUS_NOTFOUND; - goto done; - } - - /* Copy group list to client */ - - for (i = 0; i < num_gids; i++) { - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s (%d): " - "processing gid %d \n", getpid(), - user, group, gid_list[i]); -#endif - - /* Skip primary group */ - - if (gid_list[i] == group) { - continue; - } - - /* Filled buffer ? If so, resize. */ - - if (*start == *size) { - long int newsize; - gid_t *newgroups; - - newsize = 2 * (*size); - if (limit > 0) { - if (*size == limit) { - goto done; - } - if (newsize > limit) { - newsize = limit; - } - } - - newgroups = (gid_t *) - realloc((*groups), - newsize * sizeof(**groups)); - if (!newgroups) { - *errnop = ENOMEM; - ret = NSS_STATUS_NOTFOUND; - goto done; - } - *groups = newgroups; - *size = newsize; - } - - /* Add to buffer */ - - (*groups)[*start] = gid_list[i]; - *start += 1; - } - } - - /* Back to your regularly scheduled programming */ - - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(), - user, nss_err_str(ret), ret); -#endif - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - - -/* return a list of group SIDs for a user SID */ -NSS_STATUS -_nss_winbind_getusersids(const char *user_sid, char **group_sids, - int *num_groups, - char *buffer, size_t buf_size, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response); - - if (ret != NSS_STATUS_SUCCESS) { - goto done; - } - - if (buf_size < response.length - sizeof(response)) { - ret = NSS_STATUS_TRYAGAIN; - errno = *errnop = ERANGE; - goto done; - } - - *num_groups = response.data.num_entries; - *group_sids = buffer; - memcpy(buffer, response.extra_data.data, response.length - sizeof(response)); - errno = *errnop = 0; - - done: - winbindd_free_response(&response); - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - - -/* map a user or group name to a SID string */ -NSS_STATUS -_nss_winbind_nametosid(const char *name, char **sid, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.name.name, name, - sizeof(request.data.name.name) - 1); - request.data.name.name[sizeof(request.data.name.name) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - if (buflen < strlen(response.data.sid.sid)+1) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - *errnop = errno = 0; - *sid = buffer; - strcpy(*sid, response.data.sid.sid); - -failed: - winbindd_free_response(&response); - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* map a sid string to a user or group name */ -NSS_STATUS -_nss_winbind_sidtoname(const char *sid, char **name, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - static char sep_char; - unsigned needed; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - /* we need to fetch the separator first time through */ - if (!sep_char) { - ret = winbindd_request_response(WINBINDD_INFO, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - sep_char = response.data.info.winbind_separator; - winbindd_free_response(&response); - } - - - strncpy(request.data.sid, sid, - sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - needed = - strlen(response.data.name.dom_name) + - strlen(response.data.name.name) + 2; - - if (buflen < needed) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - snprintf(buffer, needed, "%s%c%s", - response.data.name.dom_name, - sep_char, - response.data.name.name); - - *name = buffer; - *errnop = errno = 0; - -failed: - winbindd_free_response(&response); - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* map a sid to a uid */ -NSS_STATUS -_nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - *uid = response.data.uid; - -failed: - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* map a sid to a gid */ -NSS_STATUS -_nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - *gid = response.data.gid; - -failed: - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* map a uid to a SID string */ -NSS_STATUS -_nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - if (buflen < strlen(response.data.sid.sid)+1) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - *errnop = errno = 0; - *sid = buffer; - strcpy(*sid, response.data.sid.sid); - -failed: - winbindd_free_response(&response); - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} - -/* map a gid to a SID string */ -NSS_STATUS -_nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid); -#endif - -#if HAVE_PTHREAD - pthread_mutex_lock(&winbind_nss_mutex); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.gid = gid; - - ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - if (buflen < strlen(response.data.sid.sid)+1) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - *errnop = errno = 0; - *sid = buffer; - strcpy(*sid, response.data.sid.sid); - -failed: - winbindd_free_response(&response); - -#if HAVE_PTHREAD - pthread_mutex_unlock(&winbind_nss_mutex); -#endif - - return ret; -} diff --git a/source3/nsswitch/winbind_nss_linux.h b/source3/nsswitch/winbind_nss_linux.h deleted file mode 100644 index 74aaec5ce6..0000000000 --- a/source3/nsswitch/winbind_nss_linux.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_LINUX_H -#define _WINBIND_NSS_LINUX_H - -#include - -typedef enum nss_status NSS_STATUS; - -#endif /* _WINBIND_NSS_LINUX_H */ diff --git a/source3/nsswitch/winbind_nss_netbsd.c b/source3/nsswitch/winbind_nss_netbsd.c deleted file mode 100644 index 9b8e0a2265..0000000000 --- a/source3/nsswitch/winbind_nss_netbsd.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - NetBSD loadable authentication module, providing identification - routines against Samba winbind/Windows NT Domain - - Copyright (C) Luke Mewburn 2004-2005 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - - -#include "winbind_client.h" - -#include -#include -#include - - /* dynamic nsswitch with "new" getpw* nsdispatch API available */ -#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R) - -/* - group functions - --------------- -*/ - -static struct group _winbind_group; -static char _winbind_groupbuf[1024]; - -/* - * We need a proper prototype for this :-) - */ - -NSS_STATUS _nss_winbind_setpwent(void); -NSS_STATUS _nss_winbind_endpwent(void); -NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_setgrent(void); -NSS_STATUS _nss_winbind_endgrent(void); -NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, - long int limit, int *errnop); -NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, - int *num_groups, char *buffer, size_t buf_size, - int *errnop); -NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); -NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); -NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, - size_t buflen, int *errnop); - -int -netbsdwinbind_endgrent(void *nsrv, void *nscb, va_list ap) -{ - int rv; - - rv = _nss_winbind_endgrent(); - return rv; -} - -int -netbsdwinbind_setgrent(void *nsrv, void *nscb, va_list ap) -{ - int rv; - - rv = _nss_winbind_setgrent(); - return rv; -} - -int -netbsdwinbind_getgrent(void *nsrv, void *nscb, va_list ap) -{ - struct group **retval = va_arg(ap, struct group **); - - int rv, rerrno; - - *retval = NULL; - rv = _nss_winbind_getgrent_r(&_winbind_group, - _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno); - if (rv == NS_SUCCESS) - *retval = &_winbind_group; - return rv; -} - -int -netbsdwinbind_getgrent_r(void *nsrv, void *nscb, va_list ap) -{ - int *retval = va_arg(ap, int *); - struct group *grp = va_arg(ap, struct group *); - char *buffer = va_arg(ap, char *); - size_t buflen = va_arg(ap, size_t); - struct group **result = va_arg(ap, struct group **); - - int rv, rerrno; - - *result = NULL; - rerrno = 0; - - rv = _nss_winbind_getgrent_r(grp, buffer, buflen, rerrno); - if (rv == NS_SUCCESS) - *result = grp; - else - *retval = rerrno; - return rv; -} - -int -netbsdwinbind_getgrgid(void *nsrv, void *nscb, va_list ap) -{ - struct group **retval = va_arg(ap, struct group **); - gid_t gid = va_arg(ap, gid_t); - - int rv, rerrno; - - *retval = NULL; - rv = _nss_winbind_getgrgid_r(gid, &_winbind_group, - _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno); - if (rv == NS_SUCCESS) - *retval = &_winbind_group; - return rv; -} - -int -netbsdwinbind_getgrgid_r(void *nsrv, void *nscb, va_list ap) -{ - int *retval = va_arg(ap, int *); - gid_t gid = va_arg(ap, gid_t); - struct group *grp = va_arg(ap, struct group *); - char *buffer = va_arg(ap, char *); - size_t buflen = va_arg(ap, size_t); - struct group **result = va_arg(ap, struct group **); - - int rv, rerrno; - - *result = NULL; - rerrno = 0; - - rv = _nss_winbind_getgrgid_r(gid, grp, buffer, buflen, &rerrno); - if (rv == NS_SUCCESS) - *result = grp; - else - *retval = rerrno; - return rv; -} - -int -netbsdwinbind_getgrnam(void *nsrv, void *nscb, va_list ap) -{ - struct group **retval = va_arg(ap, struct group **); - const char *name = va_arg(ap, const char *); - - int rv, rerrno; - - *retval = NULL; - rv = _nss_winbind_getgrnam_r(name, &_winbind_group, - _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno); - if (rv == NS_SUCCESS) - *retval = &_winbind_group; - return rv; -} - -int -netbsdwinbind_getgrnam_r(void *nsrv, void *nscb, va_list ap) -{ - int *retval = va_arg(ap, int *); - const char *name = va_arg(ap, const char *); - struct group *grp = va_arg(ap, struct group *); - char *buffer = va_arg(ap, char *); - size_t buflen = va_arg(ap, size_t); - struct group **result = va_arg(ap, struct group **); - - int rv, rerrno; - - *result = NULL; - rerrno = 0; - - rv = _nss_winbind_getgrnam_r(name, grp, buffer, buflen, &rerrno); - if (rv == NS_SUCCESS) - *result = grp; - else - *retval = rerrno; - return rv; -} - -int -netbsdwinbind_getgroupmembership(void *nsrv, void *nscb, va_list ap) -{ - int *result = va_arg(ap, int *); - const char *uname = va_arg(ap, const char *); - gid_t agroup = va_arg(ap, gid_t); - gid_t *groups = va_arg(ap, gid_t *); - int maxgrp = va_arg(ap, int); - int *groupc = va_arg(ap, int *); - - struct winbindd_request request; - struct winbindd_response response; - gid_t *wblistv; - int wblistc, i, isdup, dupc; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - strncpy(request.data.username, uname, - sizeof(request.data.username) - 1); - i = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); - if (i != NSS_STATUS_SUCCESS) - return NS_NOTFOUND; - wblistv = (gid_t *)response.extra_data.data; - wblistc = response.data.num_entries; - - for (i = 0; i < wblistc; i++) { /* add winbind gids */ - isdup = 0; /* skip duplicates */ - for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) { - if (groups[dupc] == wblistv[i]) { - isdup = 1; - break; - } - } - if (isdup) - continue; - if (*groupc < maxgrp) /* add this gid */ - groups[*groupc] = wblistv[i]; - else - *result = -1; - (*groupc)++; - } - SAFE_FREE(wblistv); - return NS_NOTFOUND; -} - - -/* - passwd functions - ---------------- -*/ - -static struct passwd _winbind_passwd; -static char _winbind_passwdbuf[1024]; - -int -netbsdwinbind_endpwent(void *nsrv, void *nscb, va_list ap) -{ - int rv; - - rv = _nss_winbind_endpwent(); - return rv; -} - -int -netbsdwinbind_setpwent(void *nsrv, void *nscb, va_list ap) -{ - int rv; - - rv = _nss_winbind_setpwent(); - return rv; -} - -int -netbsdwinbind_getpwent(void *nsrv, void *nscb, va_list ap) -{ - struct passwd **retval = va_arg(ap, struct passwd **); - - int rv, rerrno; - - *retval = NULL; - - rv = _nss_winbind_getpwent_r(&_winbind_passwd, - _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno); - if (rv == NS_SUCCESS) - *retval = &_winbind_passwd; - return rv; -} - -int -netbsdwinbind_getpwent_r(void *nsrv, void *nscb, va_list ap) -{ - int *retval = va_arg(ap, int *); - struct passwd *pw = va_arg(ap, struct passwd *); - char *buffer = va_arg(ap, char *); - size_t buflen = va_arg(ap, size_t); - struct passwd **result = va_arg(ap, struct passwd **); - - int rv, rerrno; - - *result = NULL; - rerrno = 0; - - rv = _nss_winbind_getpwent_r(pw, buffer, buflen, rerrno); - if (rv == NS_SUCCESS) - *result = pw; - else - *retval = rerrno; - return rv; -} - -int -netbsdwinbind_getpwnam(void *nsrv, void *nscb, va_list ap) -{ - struct passwd **retval = va_arg(ap, struct passwd **); - const char *name = va_arg(ap, const char *); - - int rv, rerrno; - - *retval = NULL; - rv = _nss_winbind_getpwnam_r(name, &_winbind_passwd, - _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno); - if (rv == NS_SUCCESS) - *retval = &_winbind_passwd; - return rv; -} - -int -netbsdwinbind_getpwnam_r(void *nsrv, void *nscb, va_list ap) -{ - int *retval = va_arg(ap, int *); - const char *name = va_arg(ap, const char *); - struct passwd *pw = va_arg(ap, struct passwd *); - char *buffer = va_arg(ap, char *); - size_t buflen = va_arg(ap, size_t); - struct passwd **result = va_arg(ap, struct passwd **); - - int rv, rerrno; - - *result = NULL; - rerrno = 0; - - rv = _nss_winbind_getpwnam_r(name, pw, buffer, buflen, &rerrno); - if (rv == NS_SUCCESS) - *result = pw; - else - *retval = rerrno; - return rv; -} - -int -netbsdwinbind_getpwuid(void *nsrv, void *nscb, va_list ap) -{ - struct passwd **retval = va_arg(ap, struct passwd **); - uid_t uid = va_arg(ap, uid_t); - - int rv, rerrno; - - *retval = NULL; - rv = _nss_winbind_getpwuid_r(uid, &_winbind_passwd, - _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno); - if (rv == NS_SUCCESS) - *retval = &_winbind_passwd; - return rv; -} - -int -netbsdwinbind_getpwuid_r(void *nsrv, void *nscb, va_list ap) -{ - int *retval = va_arg(ap, int *); - uid_t uid = va_arg(ap, uid_t); - struct passwd *pw = va_arg(ap, struct passwd *); - char *buffer = va_arg(ap, char *); - size_t buflen = va_arg(ap, size_t); - struct passwd **result = va_arg(ap, struct passwd **); - - int rv, rerrno; - - *result = NULL; - rerrno = 0; - - rv = _nss_winbind_getpwuid_r(uid, pw, buffer, buflen, &rerrno); - if (rv == NS_SUCCESS) - *result = pw; - else - *retval = rerrno; - return rv; -} - - -/* - nsswitch module setup - --------------------- -*/ - - -static ns_mtab winbind_methods[] = { - -{ NSDB_GROUP, "endgrent", netbsdwinbind_endgrent, NULL }, -{ NSDB_GROUP, "getgrent", netbsdwinbind_getgrent, NULL }, -{ NSDB_GROUP, "getgrent_r", netbsdwinbind_getgrent_r, NULL }, -{ NSDB_GROUP, "getgrgid", netbsdwinbind_getgrgid, NULL }, -{ NSDB_GROUP, "getgrgid_r", netbsdwinbind_getgrgid_r, NULL }, -{ NSDB_GROUP, "getgrnam", netbsdwinbind_getgrnam, NULL }, -{ NSDB_GROUP, "getgrnam_r", netbsdwinbind_getgrnam_r, NULL }, -{ NSDB_GROUP, "setgrent", netbsdwinbind_setgrent, NULL }, -{ NSDB_GROUP, "setgroupent", netbsdwinbind_setgrent, NULL }, -{ NSDB_GROUP, "getgroupmembership", netbsdwinbind_getgroupmembership, NULL }, - -{ NSDB_PASSWD, "endpwent", netbsdwinbind_endpwent, NULL }, -{ NSDB_PASSWD, "getpwent", netbsdwinbind_getpwent, NULL }, -{ NSDB_PASSWD, "getpwent_r", netbsdwinbind_getpwent_r, NULL }, -{ NSDB_PASSWD, "getpwnam", netbsdwinbind_getpwnam, NULL }, -{ NSDB_PASSWD, "getpwnam_r", netbsdwinbind_getpwnam_r, NULL }, -{ NSDB_PASSWD, "getpwuid", netbsdwinbind_getpwuid, NULL }, -{ NSDB_PASSWD, "getpwuid_r", netbsdwinbind_getpwuid_r, NULL }, -{ NSDB_PASSWD, "setpassent", netbsdwinbind_setpwent, NULL }, -{ NSDB_PASSWD, "setpwent", netbsdwinbind_setpwent, NULL }, - -}; - -ns_mtab * -nss_module_register(const char *source, unsigned int *mtabsize, - nss_module_unregister_fn *unreg) -{ - *mtabsize = sizeof(winbind_methods)/sizeof(winbind_methods[0]); - *unreg = NULL; - return (winbind_methods); -} - -#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */ diff --git a/source3/nsswitch/winbind_nss_netbsd.h b/source3/nsswitch/winbind_nss_netbsd.h deleted file mode 100644 index dceb57c784..0000000000 --- a/source3/nsswitch/winbind_nss_netbsd.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - NetBSD loadable authentication module, providing identification - routines against Samba winbind/Windows NT Domain - - Copyright (C) Luke Mewburn 2004-2005 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_NETBSD_H -#define _WINBIND_NSS_NETBSD_H - -#include - - /* dynamic nsswitch with "new" getpw* nsdispatch API available */ -#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R) - -typedef int NSS_STATUS; - -#define NSS_STATUS_SUCCESS NS_SUCCESS -#define NSS_STATUS_NOTFOUND NS_NOTFOUND -#define NSS_STATUS_UNAVAIL NS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NS_TRYAGAIN - -#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */ - -#endif /* _WINBIND_NSS_NETBSD_H */ diff --git a/source3/nsswitch/winbind_nss_solaris.c b/source3/nsswitch/winbind_nss_solaris.c deleted file mode 100644 index 865b6ebbb0..0000000000 --- a/source3/nsswitch/winbind_nss_solaris.c +++ /dev/null @@ -1,654 +0,0 @@ -/* - Solaris NSS wrapper for winbind - - Shirish Kalele 2000 - - Based on Luke Howard's ldap_nss module for Solaris - */ - -/* - Copyright (C) 1997-2003 Luke Howard. - This file is part of the nss_ldap library. - - The nss_ldap library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version. - - The nss_ldap library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the nss_ldap library; see the file COPYING.LIB. If not, - see . -*/ - -#undef DEVELOPER - -#include "winbind_client.h" -#include -#include -#include -#include -#include -#include "includes.h" -#include -#if !defined(HPUX) -#include -#endif /*hpux*/ - -#if defined(HAVE_NSS_COMMON_H) || defined(HPUX) - -#undef NSS_DEBUG - -#ifdef NSS_DEBUG -#define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str); -#else -#define NSS_DEBUG(str) ; -#endif - -#define NSS_ARGS(args) ((nss_XbyY_args_t *)args) - -#ifdef HPUX - -/* - * HP-UX 11 has no definiton of the nss_groupsbymem structure. This - * definition is taken from the nss_ldap project at: - * http://www.padl.com/OSS/nss_ldap.html - */ - -struct nss_groupsbymem { - const char *username; - gid_t *gid_array; - int maxgids; - int force_slow_way; - int (*str2ent)(const char *instr, int instr_len, void *ent, - char *buffer, int buflen); - nss_status_t (*process_cstr)(const char *instr, int instr_len, - struct nss_groupsbymem *); - int numgids; -}; - -#endif /* HPUX */ - -#define make_pwent_str(dest, src) \ -{ \ - if((dest = get_static(buffer, buflen, strlen(src)+1)) == NULL) \ - { \ - *errnop = ERANGE; \ - NSS_DEBUG("ERANGE error"); \ - return NSS_STATUS_TRYAGAIN; \ - } \ - strcpy(dest, src); \ -} - -static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_setpwent_solwrap"); - return _nss_winbind_setpwent(); -} - -static NSS_STATUS -_nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args) -{ - NSS_DEBUG("_nss_winbind_endpwent_solwrap"); - return _nss_winbind_endpwent(); -} - -static NSS_STATUS -_nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args) -{ - NSS_STATUS ret; - char* buffer = NSS_ARGS(args)->buf.buffer; - int buflen = NSS_ARGS(args)->buf.buflen; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - int* errnop = &NSS_ARGS(args)->erange; - char logmsg[80]; - - ret = _nss_winbind_getpwent_r(result, buffer, - buflen, errnop); - - if(ret == NSS_STATUS_SUCCESS) - { - snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n", - result->pw_name); - NSS_DEBUG(logmsg); - NSS_ARGS(args)->returnval = (void*) result; - } else { - snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret); - NSS_DEBUG(logmsg); - } - - return ret; -} - -static NSS_STATUS -_nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getpwnam_solwrap"); - - ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getpwuid_solwrap"); - ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args) -{ - SAFE_FREE(be); - NSS_DEBUG("_nss_winbind_passwd_destr"); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t passwd_ops[] = -{ - _nss_winbind_passwd_destr, - _nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */ - _nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */ - _nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */ - _nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */ - _nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */ -}; - -nss_backend_t* -_nss_winbind_passwd_constr (const char* db_name, - const char* src_name, - const char* cfg_args) -{ - nss_backend_t *be; - - if(!(be = SMB_MALLOC_P(nss_backend_t)) ) - return NULL; - - be->ops = passwd_ops; - be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t); - - NSS_DEBUG("Initialized nss_winbind passwd backend"); - return be; -} - -/***************************************************************** - GROUP database backend - *****************************************************************/ - -static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_setgrent_solwrap"); - return _nss_winbind_setgrent(); -} - -static NSS_STATUS -_nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args) -{ - NSS_DEBUG("_nss_winbind_endgrent_solwrap"); - return _nss_winbind_endgrent(); -} - -static NSS_STATUS -_nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - char* buffer = NSS_ARGS(args)->buf.buffer; - int buflen = NSS_ARGS(args)->buf.buflen; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - int* errnop = &NSS_ARGS(args)->erange; - char logmsg[80]; - - ret = _nss_winbind_getgrent_r(result, buffer, - buflen, errnop); - - if(ret == NSS_STATUS_SUCCESS) - { - snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name); - NSS_DEBUG(logmsg); - NSS_ARGS(args)->returnval = (void*) result; - } else { - snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret); - NSS_DEBUG(logmsg); - } - - return ret; - -} - -static NSS_STATUS -_nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getgrnam_solwrap"); - ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getgrgid_solwrap"); - ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args) -{ - int errnop; - struct nss_groupsbymem *gmem = (struct nss_groupsbymem *)args; - - NSS_DEBUG("_nss_winbind_getgroupsbymember"); - - _nss_winbind_initgroups_dyn(gmem->username, - gmem->gid_array[0], /* Primary Group */ - &gmem->numgids, - &gmem->maxgids, - &gmem->gid_array, - gmem->maxgids, - &errnop); - - /* - * If the maximum number of gids have been found, return - * SUCCESS so the switch engine will stop searching. Otherwise - * return NOTFOUND so nsswitch will continue to get groups - * from the remaining database backends specified in the - * nsswitch.conf file. - */ - return (gmem->numgids == gmem->maxgids ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND); -} - -static NSS_STATUS -_nss_winbind_group_destr (nss_backend_t* be, void* args) -{ - SAFE_FREE(be); - NSS_DEBUG("_nss_winbind_group_destr"); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t group_ops[] = -{ - _nss_winbind_group_destr, - _nss_winbind_endgrent_solwrap, - _nss_winbind_setgrent_solwrap, - _nss_winbind_getgrent_solwrap, - _nss_winbind_getgrnam_solwrap, - _nss_winbind_getgrgid_solwrap, - _nss_winbind_getgroupsbymember_solwrap -}; - -nss_backend_t* -_nss_winbind_group_constr (const char* db_name, - const char* src_name, - const char* cfg_args) -{ - nss_backend_t* be; - - if(!(be = SMB_MALLOC_P(nss_backend_t)) ) - return NULL; - - be->ops = group_ops; - be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t); - - NSS_DEBUG("Initialized nss_winbind group backend"); - return be; -} - -/***************************************************************** - hosts and ipnodes backend - *****************************************************************/ -#if defined(SUNOS5) /* not compatible with HP-UX */ - -/* this parser is shared between get*byname and get*byaddr, as key type - in request is stored in different locations, I had to provide the - address family as an argument, caller must free the winbind response. */ - -static NSS_STATUS -parse_response(int af, nss_XbyY_args_t* argp, struct winbindd_response *response) -{ - struct hostent *he = (struct hostent *)argp->buf.result; - char *buffer = argp->buf.buffer; - int buflen = argp->buf.buflen; - NSS_STATUS ret; - - char *p, *data; - int addrcount = 0; - int len = 0; - struct in_addr *addrp; -#if defined(AF_INET6) - struct in6_addr *addrp6; -#endif - int i; - - /* response is tab separated list of ip addresses with hostname - and newline at the end. so at first we will strip newline - then construct list of addresses for hostent. - */ - p = strchr(response->data.winsresp, '\n'); - if(p) *p = '\0'; - else {/* it must be broken */ - argp->h_errno = NO_DATA; - return NSS_STATUS_UNAVAIL; - } - - for(; p != response->data.winsresp; p--) { - if(*p == '\t') addrcount++; - } - - if(addrcount == 0) {/* it must be broken */ - argp->h_errno = NO_DATA; - return NSS_STATUS_UNAVAIL; - } - - /* allocate space for addresses and h_addr_list */ - he->h_addrtype = af; - if( he->h_addrtype == AF_INET) { - he->h_length = sizeof(struct in_addr); - addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen, - sizeof(struct in_addr)); - addrp -= addrcount; - he->h_addr_list = (char **)ROUND_DOWN(addrp, sizeof (char*)); - he->h_addr_list -= addrcount+1; - } -#if defined(AF_INET6) - else { - he->h_length = sizeof(struct in6_addr); - addrp6 = (struct in6_addr *)ROUND_DOWN(buffer + buflen, - sizeof(struct in6_addr)); - addrp6 -= addrcount; - he->h_addr_list = (char **)ROUND_DOWN(addrp6, sizeof (char*)); - he->h_addr_list -= addrcount+1; - } -#endif - - /* buffer too small?! */ - if((char *)he->h_addr_list < buffer ) { - argp->erange = 1; - return NSS_STR_PARSE_ERANGE; - } - - data = response->data.winsresp; - for( i = 0; i < addrcount; i++) { - p = strchr(data, '\t'); - if(p == NULL) break; /* just in case... */ - - *p = '\0'; /* terminate the string */ - if(he->h_addrtype == AF_INET) { - he->h_addr_list[i] = (char *)&addrp[i]; - if ((addrp[i].s_addr = inet_addr(data)) == -1) { - argp->erange = 1; - return NSS_STR_PARSE_ERANGE; - } - } -#if defined(AF_INET6) - else { - he->h_addr_list[i] = (char *)&addrp6[i]; - if (strchr(data, ':') != 0) { - if (inet_pton(AF_INET6, data, &addrp6[i]) != 1) { - argp->erange = 1; - return NSS_STR_PARSE_ERANGE; - } - } else { - struct in_addr in4; - if ((in4.s_addr = inet_addr(data)) == -1) { - argp->erange = 1; - return NSS_STR_PARSE_ERANGE; - } - IN6_INADDR_TO_V4MAPPED(&in4, &addrp6[i]); - } - } -#endif - data = p+1; - } - - he->h_addr_list[i] = (char *)NULL; - - len = strlen(data); - if(len > he->h_addr_list - (char**)argp->buf.buffer) { - argp->erange = 1; - return NSS_STR_PARSE_ERANGE; - } - - /* this is a bit overkill to use _nss_netdb_aliases here since - there seems to be no aliases but it will create all data for us */ - he->h_aliases = _nss_netdb_aliases(data, len, buffer, - ((char*) he->h_addr_list) - buffer); - if(he->h_aliases == NULL) { - argp->erange = 1; - ret = NSS_STR_PARSE_ERANGE; - } else { - he->h_name = he->h_aliases[0]; - he->h_aliases++; - ret = NSS_STR_PARSE_SUCCESS; - } - - argp->returnval = (void*)he; - return ret; -} - -static NSS_STATUS -_nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args) -{ - nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args; - struct winbindd_response response; - struct winbindd_request request; - NSS_STATUS ret; - int af; - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - /* I assume there that AI_ADDRCONFIG cases are handled in nss - frontend code, at least it seems done so in solaris... - - we will give NO_DATA for pure IPv6; IPv4 will be returned for - AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map - IPv4 to IPv6. - */ -#if defined(AF_INET6) -#ifdef HAVE_NSS_XBYY_KEY_IPNODE - af = argp->key.ipnode.af_family; - if(af == AF_INET6 && argp->key.ipnode.flags == 0) { - argp->h_errno = NO_DATA; - return NSS_STATUS_UNAVAIL; - } -#else - /* I'm not that sure if this is correct, but... */ - af = AF_INET6; -#endif -#endif - - strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1); - request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0'; - - if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response)) - == NSS_STATUS_SUCCESS ) { - ret = parse_response(af, argp, &response); - } - - winbindd_free_response(&response); - return ret; -} - -static NSS_STATUS -_nss_winbind_hosts_getbyname(nss_backend_t* be, void *args) -{ - nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args; - struct winbindd_response response; - struct winbindd_request request; - NSS_STATUS ret; - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1); - request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0'; - - if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response)) - == NSS_STATUS_SUCCESS ) { - ret = parse_response(AF_INET, argp, &response); - } - - winbindd_free_response(&response); - return ret; -} - -static NSS_STATUS -_nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - nss_XbyY_args_t *argp = (nss_XbyY_args_t *)args; - const char *p; - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - -#if defined(AF_INET6) - /* winbindd currently does not resolve IPv6 */ - if(argp->key.hostaddr.type == AF_INET6) { - argp->h_errno = NO_DATA; - return NSS_STATUS_UNAVAIL; - } - - p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr, - request.data.winsreq, sizeof request.data.winsreq); -#else - snprintf(request.data.winsreq, sizeof request.data.winsreq, - "%u.%u.%u.%u", - ((unsigned char *)argp->key.hostaddr.addr)[0], - ((unsigned char *)argp->key.hostaddr.addr)[1], - ((unsigned char *)argp->key.hostaddr.addr)[2], - ((unsigned char *)argp->key.hostaddr.addr)[3]); -#endif - - ret = winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response); - - if( ret == NSS_STATUS_SUCCESS) { - parse_response(argp->key.hostaddr.type, argp, &response); - } - winbindd_free_response(&response); - return ret; -} - -/* winbind does not provide setent, getent, endent for wins */ -static NSS_STATUS -_nss_winbind_common_endent(nss_backend_t* be, void *args) -{ - return (NSS_STATUS_UNAVAIL); -} - -static NSS_STATUS -_nss_winbind_common_setent(nss_backend_t* be, void *args) -{ - return (NSS_STATUS_UNAVAIL); -} - -static NSS_STATUS -_nss_winbind_common_getent(nss_backend_t* be, void *args) -{ - return (NSS_STATUS_UNAVAIL); -} - -static nss_backend_t* -_nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops) -{ - nss_backend_t* be; - - if(!(be = SMB_MALLOC_P(nss_backend_t)) ) - return NULL; - - be->ops = ops; - be->n_ops = n_ops; - - return be; -} - -static NSS_STATUS -_nss_winbind_common_destr (nss_backend_t* be, void* args) -{ - SAFE_FREE(be); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t ipnodes_ops[] = { - _nss_winbind_common_destr, - _nss_winbind_common_endent, - _nss_winbind_common_setent, - _nss_winbind_common_getent, - _nss_winbind_ipnodes_getbyname, - _nss_winbind_hosts_getbyaddr, -}; - -nss_backend_t * -_nss_winbind_ipnodes_constr(dummy1, dummy2, dummy3) - const char *dummy1, *dummy2, *dummy3; -{ - return (_nss_winbind_common_constr(ipnodes_ops, - sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0]))); -} - -static nss_backend_op_t host_ops[] = { - _nss_winbind_common_destr, - _nss_winbind_common_endent, - _nss_winbind_common_setent, - _nss_winbind_common_getent, - _nss_winbind_hosts_getbyname, - _nss_winbind_hosts_getbyaddr, -}; - -nss_backend_t * -_nss_winbind_hosts_constr(dummy1, dummy2, dummy3) - const char *dummy1, *dummy2, *dummy3; -{ - return (_nss_winbind_common_constr(host_ops, - sizeof (host_ops) / sizeof (host_ops[0]))); -} - -#endif /* defined(SUNOS5) */ -#endif /* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */ diff --git a/source3/nsswitch/winbind_nss_solaris.h b/source3/nsswitch/winbind_nss_solaris.h deleted file mode 100644 index 84062dbab4..0000000000 --- a/source3/nsswitch/winbind_nss_solaris.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_SOLARIS_H -#define _WINBIND_NSS_SOLARIS_H - -/* Solaris has a broken nss_common header file containing C++ reserved names. */ -#ifndef __cplusplus -#undef class -#undef private -#undef public -#undef protected -#undef template -#undef this -#undef new -#undef delete -#undef friend -#endif - -#include - -#ifndef __cplusplus -#define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define this #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define new #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define delete #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define friend #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#endif - -#include -#include - -typedef nss_status_t NSS_STATUS; - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -/* The solaris winbind is implemented as a wrapper around the linux - version. */ - -NSS_STATUS _nss_winbind_setpwent(void); -NSS_STATUS _nss_winbind_endpwent(void); -NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result, - char* buffer, size_t buflen, int* errnop); - -NSS_STATUS _nss_winbind_setgrent(void); -NSS_STATUS _nss_winbind_endgrent(void); -NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop); - -#endif /* _WINBIND_NSS_SOLARIS_H */ diff --git a/source3/nsswitch/winbind_struct_protocol.h b/source3/nsswitch/winbind_struct_protocol.h deleted file mode 100644 index 36873f2096..0000000000 --- a/source3/nsswitch/winbind_struct_protocol.h +++ /dev/null @@ -1,516 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - Copyright (C) Gerald Carter 2006 - - You are free to use this interface definition in any way you see - fit, including without restriction, using this header in your own - products. You do not need to give any attribution. -*/ - -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0) -#endif - -#ifndef _WINBINDD_NTDOM_H -#define _WINBINDD_NTDOM_H - -#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */ - -/* Let the build environment override the public winbindd socket location. This - * is needed for launchd support -- jpeach. - */ -#ifndef WINBINDD_SOCKET_DIR -#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */ -#endif - -/* - * when compiled with socket_wrapper support - * the location of the WINBINDD_SOCKET_DIR - * can be overwritten via an environment variable - */ -#define WINBINDD_SOCKET_DIR_ENVVAR "WINBINDD_SOCKET_DIR" - -#define WINBINDD_PRIV_SOCKET_SUBDIR "winbindd_privileged" /* name of subdirectory of lp_lockdir() to hold the 'privileged' pipe */ -#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */ -#define WINBINDD_DONT_ENV "_NO_WINBINDD" -#define WINBINDD_LOCATOR_KDC_ADDRESS "WINBINDD_LOCATOR_KDC_ADDRESS" - -/* Update this when you change the interface. */ - -/* Version 20: added WINBINDD_REMOVE_MAPPING command */ - -#define WINBIND_INTERFACE_VERSION 20 - -/* Have to deal with time_t being 4 or 8 bytes due to structure alignment. - On a 64bit Linux box, we have to support a constant structure size - between /lib/libnss_winbind.so.2 and /li64/libnss_winbind.so.2. - The easiest way to do this is to always use 8byte values for time_t. */ - -#define SMB_TIME_T int64_t - -/* Socket commands */ - -enum winbindd_cmd { - - WINBINDD_INTERFACE_VERSION, /* Always a well known value */ - - /* Get users and groups */ - - WINBINDD_GETPWNAM, - WINBINDD_GETPWUID, - WINBINDD_GETGRNAM, - WINBINDD_GETGRGID, - WINBINDD_GETGROUPS, - - /* Enumerate users and groups */ - - WINBINDD_SETPWENT, - WINBINDD_ENDPWENT, - WINBINDD_GETPWENT, - WINBINDD_SETGRENT, - WINBINDD_ENDGRENT, - WINBINDD_GETGRENT, - - /* PAM authenticate and password change */ - - WINBINDD_PAM_AUTH, - WINBINDD_PAM_AUTH_CRAP, - WINBINDD_PAM_CHAUTHTOK, - WINBINDD_PAM_LOGOFF, - WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, - - /* List various things */ - - WINBINDD_LIST_USERS, /* List w/o rid->id mapping */ - WINBINDD_LIST_GROUPS, /* Ditto */ - WINBINDD_LIST_TRUSTDOM, - - /* SID conversion */ - - WINBINDD_LOOKUPSID, - WINBINDD_LOOKUPNAME, - WINBINDD_LOOKUPRIDS, - - /* Lookup functions */ - - WINBINDD_SID_TO_UID, - WINBINDD_SID_TO_GID, - WINBINDD_SIDS_TO_XIDS, - WINBINDD_UID_TO_SID, - WINBINDD_GID_TO_SID, - - WINBINDD_ALLOCATE_UID, - WINBINDD_ALLOCATE_GID, - WINBINDD_SET_MAPPING, - WINBINDD_REMOVE_MAPPING, - WINBINDD_SET_HWM, - - /* Miscellaneous other stuff */ - - WINBINDD_CHECK_MACHACC, /* Check machine account pw works */ - WINBINDD_PING, /* Just tell me winbind is running */ - WINBINDD_INFO, /* Various bit of info. Currently just tidbits */ - WINBINDD_DOMAIN_NAME, /* The domain this winbind server is a member of (lp_workgroup()) */ - - WINBINDD_DOMAIN_INFO, /* Most of what we know from - struct winbindd_domain */ - WINBINDD_GETDCNAME, /* Issue a GetDCName Request */ - WINBINDD_DSGETDCNAME, /* Issue a DsGetDCName Request */ - - WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */ - - /* WINS commands */ - - WINBINDD_WINS_BYIP, - WINBINDD_WINS_BYNAME, - - /* this is like GETGRENT but gives an empty group list */ - WINBINDD_GETGRLST, - - WINBINDD_NETBIOS_NAME, /* The netbios name of the server */ - - /* find the location of our privileged pipe */ - WINBINDD_PRIV_PIPE_DIR, - - /* return a list of group sids for a user sid */ - WINBINDD_GETUSERSIDS, - - /* Various group queries */ - WINBINDD_GETUSERDOMGROUPS, - - /* Initialize connection in a child */ - WINBINDD_INIT_CONNECTION, - - /* Blocking calls that are not allowed on the main winbind pipe, only - * between parent and children */ - WINBINDD_DUAL_SID2UID, - WINBINDD_DUAL_SID2GID, - WINBINDD_DUAL_SIDS2XIDS, - WINBINDD_DUAL_UID2SID, - WINBINDD_DUAL_GID2SID, - WINBINDD_DUAL_SET_MAPPING, - WINBINDD_DUAL_REMOVE_MAPPING, - WINBINDD_DUAL_SET_HWM, - - /* Wrapper around possibly blocking unix nss calls */ - WINBINDD_DUAL_USERINFO, - WINBINDD_DUAL_GETSIDALIASES, - - /* Complete the challenge phase of the NTLM authentication - protocol using cached password. */ - WINBINDD_CCACHE_NTLMAUTH, - - WINBINDD_NUM_CMDS -}; - -typedef struct winbindd_pw { - fstring pw_name; - fstring pw_passwd; - uid_t pw_uid; - gid_t pw_gid; - fstring pw_gecos; - fstring pw_dir; - fstring pw_shell; -} WINBINDD_PW; - - -typedef struct winbindd_gr { - fstring gr_name; - fstring gr_passwd; - gid_t gr_gid; - uint32_t num_gr_mem; - uint32_t gr_mem_ofs; /* offset to group membership */ -} WINBINDD_GR; - -/* PAM specific request flags */ -#define WBFLAG_PAM_INFO3_NDR 0x00000001 -#define WBFLAG_PAM_INFO3_TEXT 0x00000002 -#define WBFLAG_PAM_USER_SESSION_KEY 0x00000004 -#define WBFLAG_PAM_LMKEY 0x00000008 -#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x00000010 -#define WBFLAG_PAM_UNIX_NAME 0x00000080 -#define WBFLAG_PAM_AFS_TOKEN 0x00000100 -#define WBFLAG_PAM_NT_STATUS_SQUASH 0x00000200 -#define WBFLAG_PAM_KRB5 0x00001000 -#define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x00002000 -#define WBFLAG_PAM_CACHED_LOGIN 0x00004000 -#define WBFLAG_PAM_GET_PWD_POLICY 0x00008000 - -/* generic request flags */ -#define WBFLAG_QUERY_ONLY 0x00000020 /* not used */ -/* This is a flag that can only be sent from parent to child */ -#define WBFLAG_IS_PRIVILEGED 0x00000400 /* not used */ -/* Flag to say this is a winbindd internal send - don't recurse. */ -#define WBFLAG_RECURSE 0x00000800 -/* Flag to tell winbind the NTLMv2 blob is too big for the struct and is in the - * extra_data field */ -#define WBFLAG_BIG_NTLMV2_BLOB 0x00010000 - -#define WINBINDD_MAX_EXTRA_DATA (128*1024) - -/* Winbind request structure */ - -/******************************************************************************* - * This structure MUST be the same size in the 32bit and 64bit builds - * for compatibility between /lib64/libnss_winbind.so and /lib/libnss_winbind.so - * - * DO NOT CHANGE THIS STRUCTURE WITHOUT TESTING THE 32BIT NSS LIB AGAINST - * A 64BIT WINBINDD --jerry - ******************************************************************************/ - -struct winbindd_request { - uint32_t length; - enum winbindd_cmd cmd; /* Winbindd command to execute */ - enum winbindd_cmd original_cmd; /* Original Winbindd command - issued to parent process */ - pid_t pid; /* pid of calling process */ - uint32_t wb_flags; /* generic flags */ - uint32_t flags; /* flags relevant *only* to a given request */ - fstring domain_name; /* name of domain for which the request applies */ - - union { - fstring winsreq; /* WINS request */ - fstring username; /* getpwnam */ - fstring groupname; /* getgrnam */ - uid_t uid; /* getpwuid, uid_to_sid */ - gid_t gid; /* getgrgid, gid_to_sid */ - struct { - /* We deliberatedly don't split into domain/user to - avoid having the client know what the separator - character is. */ - fstring user; - fstring pass; - char require_membership_of_sid[1024]; - fstring krb5_cc_type; - uid_t uid; - } auth; /* pam_winbind auth module */ - struct { - uint8_t chal[8]; - uint32_t logon_parameters; - fstring user; - fstring domain; - fstring lm_resp; - uint32_t lm_resp_len; - fstring nt_resp; - uint32_t nt_resp_len; - fstring workstation; - fstring require_membership_of_sid; - } auth_crap; - struct { - fstring user; - fstring oldpass; - fstring newpass; - } chauthtok; /* pam_winbind passwd module */ - struct { - fstring user; - fstring domain; - uint8_t new_nt_pswd[516]; - uint16_t new_nt_pswd_len; - uint8_t old_nt_hash_enc[16]; - uint16_t old_nt_hash_enc_len; - uint8_t new_lm_pswd[516]; - uint16_t new_lm_pswd_len; - uint8_t old_lm_hash_enc[16]; - uint16_t old_lm_hash_enc_len; - } chng_pswd_auth_crap;/* pam_winbind passwd module */ - struct { - fstring user; - fstring krb5ccname; - uid_t uid; - } logoff; /* pam_winbind session module */ - fstring sid; /* lookupsid, sid_to_[ug]id */ - struct { - fstring dom_name; /* lookupname */ - fstring name; - } name; - uint32_t num_entries; /* getpwent, getgrent */ - struct { - fstring username; - fstring groupname; - } acct_mgt; - struct { - bool is_primary; - fstring dcname; - } init_conn; - struct { - fstring sid; - fstring name; - } dual_sid2id; - struct { - fstring sid; - uint32_t type; - uint32_t id; - } dual_idmapset; - bool list_all_domains; - - struct { - uid_t uid; - fstring user; - /* the effective uid of the client, must be the uid for 'user'. - This is checked by the main daemon, trusted by children. */ - /* if the blobs are length zero, then this doesn't - produce an actual challenge response. It merely - succeeds if there are cached credentials available - that could be used. */ - uint32_t initial_blob_len; /* blobs in extra_data */ - uint32_t challenge_blob_len; - } ccache_ntlm_auth; - struct { - fstring domain_name; - fstring domain_guid; - fstring site_name; - uint32_t flags; - } dsgetdcname; - - /* padding -- needed to fix alignment between 32bit and 64bit libs. - The size is the sizeof the union without the padding aligned on - an 8 byte boundary. --jerry */ - - char padding[1800]; - } data; - union { - SMB_TIME_T padding; - char *data; - } extra_data; - uint32_t extra_len; - char null_term; -}; - -/* Response values */ - -enum winbindd_result { - WINBINDD_ERROR, - WINBINDD_PENDING, - WINBINDD_OK -}; - -/* Winbind response structure */ - -/******************************************************************************* - * This structure MUST be the same size in the 32bit and 64bit builds - * for compatibility between /lib64/libnss_winbind.so and /lib/libnss_winbind.so - * - * DO NOT CHANGE THIS STRUCTURE WITHOUT TESTING THE 32BIT NSS LIB AGAINST - * A 64BIT WINBINDD --jerry - ******************************************************************************/ - -struct winbindd_response { - - /* Header information */ - - uint32_t length; /* Length of response */ - enum winbindd_result result; /* Result code */ - - /* Fixed length return data */ - - union { - int interface_version; /* Try to ensure this is always in the same spot... */ - - fstring winsresp; /* WINS response */ - - /* getpwnam, getpwuid */ - - struct winbindd_pw pw; - - /* getgrnam, getgrgid */ - - struct winbindd_gr gr; - - uint32_t num_entries; /* getpwent, getgrent */ - struct winbindd_sid { - fstring sid; /* lookupname, [ug]id_to_sid */ - int type; - } sid; - struct winbindd_name { - fstring dom_name; /* lookupsid */ - fstring name; - int type; - } name; - uid_t uid; /* sid_to_uid */ - gid_t gid; /* sid_to_gid */ - struct winbindd_info { - char winbind_separator; - fstring samba_version; - } info; - fstring domain_name; - fstring netbios_name; - fstring dc_name; - - struct auth_reply { - uint32_t nt_status; - fstring nt_status_string; - fstring error_string; - int pam_error; - char user_session_key[16]; - char first_8_lm_hash[8]; - fstring krb5ccname; - uint32_t reject_reason; - uint32_t padding; - struct policy_settings { - uint32_t min_length_password; - uint32_t password_history; - uint32_t password_properties; - uint32_t padding; - SMB_TIME_T expire; - SMB_TIME_T min_passwordage; - } policy; - struct info3_text { - SMB_TIME_T logon_time; - SMB_TIME_T logoff_time; - SMB_TIME_T kickoff_time; - SMB_TIME_T pass_last_set_time; - SMB_TIME_T pass_can_change_time; - SMB_TIME_T pass_must_change_time; - uint32_t logon_count; - uint32_t bad_pw_count; - uint32_t user_rid; - uint32_t group_rid; - uint32_t num_groups; - uint32_t user_flgs; - uint32_t acct_flags; - uint32_t num_other_sids; - fstring dom_sid; - fstring user_name; - fstring full_name; - fstring logon_script; - fstring profile_path; - fstring home_dir; - fstring dir_drive; - fstring logon_srv; - fstring logon_dom; - } info3; - fstring unix_username; - } auth; - struct { - fstring name; - fstring alt_name; - fstring sid; - bool native_mode; - bool active_directory; - bool primary; - } domain_info; - uint32_t sequence_number; - struct { - fstring acct_name; - fstring full_name; - fstring homedir; - fstring shell; - uint32_t primary_gid; - uint32_t group_rid; - } user_info; - struct { - uint32_t auth_blob_len; /* blob in extra_data */ - } ccache_ntlm_auth; - struct { - fstring dc_unc; - fstring dc_address; - uint32_t dc_address_type; - fstring domain_guid; - fstring domain_name; - fstring forest_name; - uint32_t dc_flags; - fstring dc_site_name; - fstring client_site_name; - } dsgetdcname; - } data; - - /* Variable length return data */ - - union { - SMB_TIME_T padding; - void *data; - } extra_data; -}; - -struct WINBINDD_MEMORY_CREDS { - struct WINBINDD_MEMORY_CREDS *next, *prev; - const char *username; /* lookup key. */ - uid_t uid; - int ref_count; - size_t len; - uint8_t *nt_hash; /* Base pointer for the following 2 */ - uint8_t *lm_hash; - char *pass; -}; - -struct WINBINDD_CCACHE_ENTRY { - struct WINBINDD_CCACHE_ENTRY *next, *prev; - const char *principal_name; - const char *ccname; - const char *service; - const char *username; - const char *realm; - struct WINBINDD_MEMORY_CREDS *cred_ptr; - int ref_count; - uid_t uid; - time_t create_time; - time_t renew_until; - time_t refresh_time; - struct timed_event *event; -}; - -#endif diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c deleted file mode 100644 index e028eb8cf2..0000000000 --- a/source3/nsswitch/wins.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - Unix SMB/CIFS implementation. - a WINS nsswitch module - 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 3 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, see . - -*/ - -#include "includes.h" -#ifdef HAVE_NS_API_H - -#include -#endif - -#if HAVE_PTHREAD_H -#include -#endif - -#if HAVE_PTHREAD -static pthread_mutex_t wins_nss_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif - -#ifndef INADDRSZ -#define INADDRSZ 4 -#endif - -static int initialised; - -extern bool AllowDebugChange; - -NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, - char *buffer, size_t buflen, int *h_errnop); -NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, - char *buffer, size_t buflen, int *h_errnop); - -/* Use our own create socket code so we don't recurse.... */ - -static int wins_lookup_open_socket_in(void) -{ - struct sockaddr_in sock; - int val=1; - int res; - - memset((char *)&sock,'\0',sizeof(sock)); - -#ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = 0; - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); - res = socket(AF_INET, SOCK_DGRAM, 0); - if (res == -1) - return -1; - - if (setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)) != 0) { - close(res); - return -1; - } -#ifdef SO_REUSEPORT - if (setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)) != 0) { - close(res); - return -1; - } -#endif /* SO_REUSEPORT */ - - /* now we've got a socket - we need to bind it */ - - if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { - close(res); - return(-1); - } - - set_socket_options(res,"SO_BROADCAST"); - - return res; -} - - -static void nss_wins_init(void) -{ - initialised = 1; - DEBUGLEVEL = 0; - AllowDebugChange = False; - - TimeInit(); - setup_logging("nss_wins",False); - load_case_tables(); - lp_load(get_dyn_CONFIGFILE(),True,False,False,True); - load_interfaces(); -} - -static struct in_addr *lookup_byname_backend(const char *name, int *count) -{ - int fd = -1; - struct ip_service *address = NULL; - struct in_addr *ret = NULL; - int j, flags = 0; - - if (!initialised) { - nss_wins_init(); - } - - *count = 0; - - /* always try with wins first */ - if (NT_STATUS_IS_OK(resolve_wins(name,0x00,&address,count))) { - if ( (ret = SMB_MALLOC_P(struct in_addr)) == NULL ) { - free( address ); - return NULL; - } - if (address[0].ss.ss_family != AF_INET) { - free(address); - free(ret); - return NULL; - } - *ret = ((struct sockaddr_in *)&address[0].ss)->sin_addr; - free( address ); - return ret; - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) { - return NULL; - } - - /* uggh, we have to broadcast to each interface in turn */ - for (j=iface_count() - 1;j >= 0;j--) { - const struct in_addr *bcast = iface_n_bcast_v4(j); - struct sockaddr_storage ss; - struct sockaddr_storage *pss; - if (!bcast) { - continue; - } - in_addr_to_sockaddr_storage(&ss, *bcast); - pss = name_query(fd,name,0x00,True,True,&ss,count, &flags, NULL); - if (pss) { - if ((ret = SMB_MALLOC_P(struct in_addr)) == NULL) { - return NULL; - } - *ret = ((struct sockaddr_in *)pss)->sin_addr; - break; - } - } - - close(fd); - return ret; -} - -#ifdef HAVE_NS_API_H - -static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct sockaddr_storage ss; - struct nmb_name nname; - NODE_STATUS_STRUCT *status; - - if (!initialised) { - nss_wins_init(); - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - if (!interpret_string_addr(&ss, addr, AI_NUMERICHOST)) { - return NULL; - } - status = node_status_query(fd, &nname, &ss, count, NULL); - - close(fd); - return status; -} - -/* IRIX version */ - -int init(void) -{ - nsd_logprintf(NSD_LOG_MIN, "entering init (wins)\n"); - nss_wins_init(); - return NSD_OK; -} - -int lookup(nsd_file_t *rq) -{ - char *map; - char *key; - char *addr; - struct in_addr *ip_list; - NODE_STATUS_STRUCT *status; - int i, count, len, size; - char response[1024]; - bool found = False; - - nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - if (! map) { - rq->f_status = NS_FATAL; - return NSD_ERROR; - } - - key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); - if (! key || ! *key) { - rq->f_status = NS_FATAL; - return NSD_ERROR; - } - - response[0] = '\0'; - len = sizeof(response) - 2; - - /* - * response needs to be a string of the following format - * ip_address[ ip_address]*\tname[ alias]* - */ - if (StrCaseCmp(map,"hosts.byaddr") == 0) { - if ( status = lookup_byaddr_backend(key, &count)) { - size = strlen(key) + 1; - if (size > len) { - free(status); - return NSD_ERROR; - } - len -= size; - strncat(response,key,size); - strncat(response,"\t",1); - for (i = 0; i < count; i++) { - /* ignore group names */ - if (status[i].flags & 0x80) continue; - if (status[i].type == 0x20) { - size = sizeof(status[i].name) + 1; - if (size > len) { - free(status); - return NSD_ERROR; - } - len -= size; - strncat(response, status[i].name, size); - strncat(response, " ", 1); - found = True; - } - } - response[strlen(response)-1] = '\n'; - free(status); - } - } else if (StrCaseCmp(map,"hosts.byname") == 0) { - if (ip_list = lookup_byname_backend(key, &count)) { - for (i = count; i ; i--) { - addr = inet_ntoa(ip_list[i-1]); - size = strlen(addr) + 1; - if (size > len) { - free(ip_list); - return NSD_ERROR; - } - len -= size; - if (i != 0) - response[strlen(response)-1] = ' '; - strncat(response,addr,size); - strncat(response,"\t",1); - } - size = strlen(key) + 1; - if (size > len) { - free(ip_list); - return NSD_ERROR; - } - strncat(response,key,size); - strncat(response,"\n",1); - found = True; - free(ip_list); - } - } - - if (found) { - nsd_logprintf(NSD_LOG_LOW, "lookup (wins %s) %s\n",map,response); - nsd_set_result(rq,NS_SUCCESS,response,strlen(response),VOLATILE); - return NSD_OK; - } - nsd_logprintf(NSD_LOG_LOW, "lookup (wins) not found\n"); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; -} - -#else - -/* Allocate some space from the nss static buffer. The buffer and buflen - are the pointers passed in by the C library to the _nss_*_* - functions. */ - -static char *get_static(char **buffer, size_t *buflen, int len) -{ - char *result; - - /* Error check. We return false if things aren't set up right, or - there isn't enough buffer space left. */ - - if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { - return NULL; - } - - /* Return an index into the static buffer */ - - result = *buffer; - *buffer += len; - *buflen -= len; - - return result; -} - -/**************************************************************************** -gethostbyname() - we ignore any domain portion of the name and only -handle names that are at most 15 characters long - **************************************************************************/ -NSS_STATUS -_nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, - char *buffer, size_t buflen, int *h_errnop) -{ - NSS_STATUS nss_status = NSS_STATUS_SUCCESS; - struct in_addr *ip_list; - int i, count; - fstring name; - size_t namelen; - -#if HAVE_PTHREAD - pthread_mutex_lock(&wins_nss_mutex); -#endif - - memset(he, '\0', sizeof(*he)); - fstrcpy(name, hostname); - - /* Do lookup */ - - ip_list = lookup_byname_backend(name, &count); - - if (!ip_list) { - nss_status = NSS_STATUS_NOTFOUND; - goto out; - } - - /* Copy h_name */ - - namelen = strlen(name) + 1; - - if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL) { - free(ip_list); - nss_status = NSS_STATUS_TRYAGAIN; - goto out; - } - - memcpy(he->h_name, name, namelen); - - /* Copy h_addr_list, align to pointer boundary first */ - - if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0) - i = sizeof(char*) - i; - - if (get_static(&buffer, &buflen, i) == NULL) { - free(ip_list); - nss_status = NSS_STATUS_TRYAGAIN; - goto out; - } - - if ((he->h_addr_list = (char **)get_static( - &buffer, &buflen, (count + 1) * sizeof(char *))) == NULL) { - free(ip_list); - nss_status = NSS_STATUS_TRYAGAIN; - goto out; - } - - for (i = 0; i < count; i++) { - if ((he->h_addr_list[i] = get_static(&buffer, &buflen, - INADDRSZ)) == NULL) { - free(ip_list); - nss_status = NSS_STATUS_TRYAGAIN; - goto out; - } - memcpy(he->h_addr_list[i], &ip_list[i], INADDRSZ); - } - - he->h_addr_list[count] = NULL; - - free(ip_list); - - /* Set h_addr_type and h_length */ - - he->h_addrtype = AF_INET; - he->h_length = INADDRSZ; - - /* Set h_aliases */ - - if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0) - i = sizeof(char*) - i; - - if (get_static(&buffer, &buflen, i) == NULL) { - nss_status = NSS_STATUS_TRYAGAIN; - goto out; - } - - if ((he->h_aliases = (char **)get_static( - &buffer, &buflen, sizeof(char *))) == NULL) { - nss_status = NSS_STATUS_TRYAGAIN; - goto out; - } - - he->h_aliases[0] = NULL; - - nss_status = NSS_STATUS_SUCCESS; - - out: - -#if HAVE_PTHREAD - pthread_mutex_unlock(&wins_nss_mutex); -#endif - return nss_status; -} - - -NSS_STATUS -_nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, - char *buffer, size_t buflen, int *h_errnop) -{ - NSS_STATUS nss_status; - - if(af!=AF_INET) { - *h_errnop = NO_DATA; - nss_status = NSS_STATUS_UNAVAIL; - } else { - nss_status = _nss_wins_gethostbyname_r( - name, he, buffer, buflen, h_errnop); - } - return nss_status; -} -#endif diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c index 3b97dff276..8f260eb580 100644 --- a/source4/winbind/wb_samba3_protocol.c +++ b/source4/winbind/wb_samba3_protocol.c @@ -184,7 +184,6 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call) case WINBINDD_ALLOCATE_GID: case WINBINDD_SET_MAPPING: case WINBINDD_SET_HWM: - case WINBINDD_DUMP_MAPS: case WINBINDD_DOMAIN_INFO: case WINBINDD_SHOW_SEQUENCE: case WINBINDD_WINS_BYIP: @@ -194,11 +193,6 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call) case WINBINDD_DUAL_SIDS2XIDS: case WINBINDD_DUAL_SET_MAPPING: case WINBINDD_DUAL_SET_HWM: - case WINBINDD_DUAL_DUMP_MAPS: - case WINBINDD_DUAL_UID2NAME: - case WINBINDD_DUAL_NAME2UID: - case WINBINDD_DUAL_GID2NAME: - case WINBINDD_DUAL_NAME2GID: case WINBINDD_DUAL_USERINFO: case WINBINDD_DUAL_GETSIDALIASES: case WINBINDD_CCACHE_NTLMAUTH: -- cgit From 5ee0392a55d3a35692c026f1b88909d7fd2d2666 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Tue, 16 Dec 2008 10:06:04 +0100 Subject: nsswitch: Move nsswitch files from source4 to top level nsswitch dir --- nsswitch/config.m4 | 11 + nsswitch/config.mk | 34 + nsswitch/nsstest.c | 411 +++++++++ nsswitch/nsstest.h | 115 +++ nsswitch/nsstest.m4 | 8 + nsswitch/tests/test_wbinfo.sh | 186 ++++ nsswitch/wbinfo4.c | 1294 ++++++++++++++++++++++++++++ source3/samba4.m4 | 4 +- source3/samba4.mk | 4 +- source4/Makefile | 2 +- source4/configure.ac | 4 +- source4/main.mk | 2 +- source4/nsswitch/config.m4 | 12 - source4/nsswitch/config.mk | 34 - source4/nsswitch/nsstest.c | 411 --------- source4/nsswitch/nsstest.h | 115 --- source4/nsswitch/nsstest.m4 | 9 - source4/nsswitch/tests/test_wbinfo.sh | 187 ---- source4/nsswitch/wb_common.c | 698 --------------- source4/nsswitch/wbinfo.c | 1290 --------------------------- source4/nsswitch/winbind_client.h | 25 - source4/nsswitch/winbind_nss.h | 76 -- source4/nsswitch/winbind_nss_config.h | 53 -- source4/nsswitch/winbind_nss_hpux.h | 137 --- source4/nsswitch/winbind_nss_irix.h | 42 - source4/nsswitch/winbind_nss_linux.c | 1281 --------------------------- source4/nsswitch/winbind_nss_linux.h | 29 - source4/nsswitch/winbind_nss_netbsd.h | 40 - source4/nsswitch/winbind_nss_solaris.h | 89 -- source4/nsswitch/winbind_struct_protocol.h | 507 ----------- source4/winbind/wb_samba3_protocol.c | 3 + 31 files changed, 2070 insertions(+), 5043 deletions(-) create mode 100644 nsswitch/config.m4 create mode 100644 nsswitch/config.mk create mode 100644 nsswitch/nsstest.c create mode 100644 nsswitch/nsstest.h create mode 100644 nsswitch/nsstest.m4 create mode 100755 nsswitch/tests/test_wbinfo.sh create mode 100644 nsswitch/wbinfo4.c delete mode 100644 source4/nsswitch/config.m4 delete mode 100644 source4/nsswitch/config.mk delete mode 100644 source4/nsswitch/nsstest.c delete mode 100644 source4/nsswitch/nsstest.h delete mode 100644 source4/nsswitch/nsstest.m4 delete mode 100755 source4/nsswitch/tests/test_wbinfo.sh delete mode 100644 source4/nsswitch/wb_common.c delete mode 100644 source4/nsswitch/wbinfo.c delete mode 100644 source4/nsswitch/winbind_client.h delete mode 100644 source4/nsswitch/winbind_nss.h delete mode 100644 source4/nsswitch/winbind_nss_config.h delete mode 100644 source4/nsswitch/winbind_nss_hpux.h delete mode 100644 source4/nsswitch/winbind_nss_irix.h delete mode 100644 source4/nsswitch/winbind_nss_linux.c delete mode 100644 source4/nsswitch/winbind_nss_linux.h delete mode 100644 source4/nsswitch/winbind_nss_netbsd.h delete mode 100644 source4/nsswitch/winbind_nss_solaris.h delete mode 100644 source4/nsswitch/winbind_struct_protocol.h diff --git a/nsswitch/config.m4 b/nsswitch/config.m4 new file mode 100644 index 0000000000..2c8fa17ad9 --- /dev/null +++ b/nsswitch/config.m4 @@ -0,0 +1,11 @@ +AC_CHECK_HEADERS(nss.h nss_common.h ns_api.h ) + +case "$host_os" in + *linux*) + SMB_LIBRARY(nss_winbind, + [../nsswitch/winbind_nss_linux.o], + [LIBWINBIND-CLIENT]) + ;; + *) + ;; +esac diff --git a/nsswitch/config.mk b/nsswitch/config.mk new file mode 100644 index 0000000000..3a4f054d1f --- /dev/null +++ b/nsswitch/config.mk @@ -0,0 +1,34 @@ +[SUBSYSTEM::LIBWINBIND-CLIENT] +PRIVATE_DEPENDENCIES = SOCKET_WRAPPER + +LIBWINBIND-CLIENT_OBJ_FILES = $(nsswitchsrcdir)/wb_common.o + +################################# +# Start BINARY nsstest +[BINARY::nsstest] +INSTALLDIR = BINDIR +PRIVATE_DEPENDENCIES = \ + LIBSAMBA-UTIL \ + LIBREPLACE_EXT \ + LIBSAMBA-HOSTCONFIG +# End BINARY nsstest +################################# + +nsstest_OBJ_FILES = $(nsswitchsrcdir)/nsstest.o + +################################# +# Start BINARY wbinfo +[BINARY::wbinfo] +INSTALLDIR = BINDIR +PRIVATE_DEPENDENCIES = \ + LIBSAMBA-UTIL \ + LIBREPLACE_EXT \ + LIBCLI_AUTH \ + LIBPOPT \ + POPT_SAMBA \ + LIBWINBIND-CLIENT +# End BINARY nsstest +################################# + +wbinfo_OBJ_FILES = \ + $(nsswitchsrcdir)/wbinfo4.o diff --git a/nsswitch/nsstest.c b/nsswitch/nsstest.c new file mode 100644 index 0000000000..26f816f5d1 --- /dev/null +++ b/nsswitch/nsstest.c @@ -0,0 +1,411 @@ +/* + Unix SMB/CIFS implementation. + nss tester for winbindd + Copyright (C) Andrew Tridgell 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 3 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, see . +*/ + +#include "includes.h" + +#include "nsswitch/nsstest.h" + +static const char *so_path = "/lib/libnss_winbind.so"; +static const char *nss_name = "winbind"; +static int nss_errno; +static NSS_STATUS last_error; +static int total_errors; + +static void *find_fn(const char *name) +{ + char s[1024]; + static void *h; + void *res; + + snprintf(s,sizeof(s), "_nss_%s_%s", nss_name, name); + + if (!h) { + h = dlopen(so_path, RTLD_LAZY); + } + if (!h) { + printf("Can't open shared library %s\n", so_path); + exit(1); + } + res = dlsym(h, s); + if (!res) { + printf("Can't find function %s\n", s); + return NULL; + } + return res; +} + +static void report_nss_error(const char *who, NSS_STATUS status) +{ + last_error = status; + total_errors++; + printf("ERROR %s: NSS_STATUS=%d %d (nss_errno=%d)\n", + who, status, NSS_STATUS_SUCCESS, nss_errno); +} + +static struct passwd *nss_getpwent(void) +{ + NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, + size_t , int *) = find_fn("getpwent_r"); + static struct passwd pwd; + static char buf[1000]; + NSS_STATUS status; + + status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno); + if (status == NSS_STATUS_NOTFOUND) { + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("getpwent", status); + return NULL; + } + return &pwd; +} + +static struct passwd *nss_getpwnam(const char *name) +{ + NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, + size_t , int *) = find_fn("getpwnam_r"); + static struct passwd pwd; + static char buf[1000]; + NSS_STATUS status; + + status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno); + if (status == NSS_STATUS_NOTFOUND) { + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("getpwnam", status); + return NULL; + } + return &pwd; +} + +static struct passwd *nss_getpwuid(uid_t uid) +{ + NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *, + size_t , int *) = find_fn("getpwuid_r"); + static struct passwd pwd; + static char buf[1000]; + NSS_STATUS status; + + status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno); + if (status == NSS_STATUS_NOTFOUND) { + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("getpwuid", status); + return NULL; + } + return &pwd; +} + +static void nss_setpwent(void) +{ + NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent"); + NSS_STATUS status; + status = _nss_setpwent(); + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("setpwent", status); + } +} + +static void nss_endpwent(void) +{ + NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent"); + NSS_STATUS status; + status = _nss_endpwent(); + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("endpwent", status); + } +} + + +static struct group *nss_getgrent(void) +{ + NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, + size_t , int *) = find_fn("getgrent_r"); + static struct group grp; + static char *buf; + static int buflen = 1024; + NSS_STATUS status; + + if (!buf) buf = malloc_array_p(char, buflen); + +again: + status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno); + if (status == NSS_STATUS_TRYAGAIN) { + buflen *= 2; + buf = realloc_p(buf, char, buflen); + goto again; + } + if (status == NSS_STATUS_NOTFOUND) { + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("getgrent", status); + return NULL; + } + return &grp; +} + +static struct group *nss_getgrnam(const char *name) +{ + NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, + size_t , int *) = find_fn("getgrnam_r"); + static struct group grp; + static char *buf; + static int buflen = 1000; + NSS_STATUS status; + + if (!buf) buf = malloc_array_p(char, buflen); +again: + status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno); + if (status == NSS_STATUS_TRYAGAIN) { + buflen *= 2; + buf = realloc_p(buf, char, buflen); + goto again; + } + if (status == NSS_STATUS_NOTFOUND) { + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("getgrnam", status); + return NULL; + } + return &grp; +} + +static struct group *nss_getgrgid(gid_t gid) +{ + NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, + size_t , int *) = find_fn("getgrgid_r"); + static struct group grp; + static char *buf; + static int buflen = 1000; + NSS_STATUS status; + + if (!buf) buf = malloc_array_p(char, buflen); +again: + status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno); + if (status == NSS_STATUS_TRYAGAIN) { + buflen *= 2; + buf = realloc_p(buf, char, buflen); + goto again; + } + if (status == NSS_STATUS_NOTFOUND) { + return NULL; + } + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("getgrgid", status); + return NULL; + } + return &grp; +} + +static void nss_setgrent(void) +{ + NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent"); + NSS_STATUS status; + status = _nss_setgrent(); + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("setgrent", status); + } +} + +static void nss_endgrent(void) +{ + NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent"); + NSS_STATUS status; + status = _nss_endgrent(); + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("endgrent", status); + } +} + +static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *start, long int *size) +{ + NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *, + long int *, gid_t **, long int , int *) = + find_fn("initgroups_dyn"); + NSS_STATUS status; + + if (!_nss_initgroups) return NSS_STATUS_UNAVAIL; + + status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno); + if (status != NSS_STATUS_SUCCESS) { + report_nss_error("initgroups", status); + } + return status; +} + +static void print_passwd(struct passwd *pwd) +{ + printf("%s:%s:%d:%d:%s:%s:%s\n", + pwd->pw_name, + pwd->pw_passwd, + pwd->pw_uid, + pwd->pw_gid, + pwd->pw_gecos, + pwd->pw_dir, + pwd->pw_shell); +} + +static void print_group(struct group *grp) +{ + int i; + printf("%s:%s:%d: ", + grp->gr_name, + grp->gr_passwd, + grp->gr_gid); + + if (!grp->gr_mem[0]) { + printf("\n"); + return; + } + + for (i=0; grp->gr_mem[i+1]; i++) { + printf("%s, ", grp->gr_mem[i]); + } + printf("%s\n", grp->gr_mem[i]); +} + +static void nss_test_initgroups(char *name, gid_t gid) +{ + long int size = 16; + long int start = 1; + gid_t *groups = NULL; + int i; + NSS_STATUS status; + + groups = (gid_t *)malloc_array_p(gid_t, size); + groups[0] = gid; + + status = nss_initgroups(name, gid, &groups, &start, &size); + if (status == NSS_STATUS_UNAVAIL) { + printf("No initgroups fn\n"); + return; + } + + for (i=0; ipw_name); + printf("getpwent: "); print_passwd(pwd); + pwd = nss_getpwuid(pwd->pw_uid); + if (!pwd) { + total_errors++; + printf("ERROR: can't getpwuid\n"); + continue; + } + printf("getpwuid: "); print_passwd(pwd); + pwd = nss_getpwnam(pwd->pw_name); + if (!pwd) { + total_errors++; + printf("ERROR: can't getpwnam\n"); + continue; + } + printf("getpwnam: "); print_passwd(pwd); + printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid); + printf("\n"); + } + nss_endpwent(); +} + +static void nss_test_groups(void) +{ + struct group *grp; + + nss_setgrent(); + /* loop over all groups */ + while ((grp = nss_getgrent())) { + printf("Testing group %s\n", grp->gr_name); + printf("getgrent: "); print_group(grp); + grp = nss_getgrnam(grp->gr_name); + if (!grp) { + total_errors++; + printf("ERROR: can't getgrnam\n"); + continue; + } + printf("getgrnam: "); print_group(grp); + grp = nss_getgrgid(grp->gr_gid); + if (!grp) { + total_errors++; + printf("ERROR: can't getgrgid\n"); + continue; + } + printf("getgrgid: "); print_group(grp); + printf("\n"); + } + nss_endgrent(); +} + +static void nss_test_errors(void) +{ + struct passwd *pwd; + struct group *grp; + + pwd = getpwnam("nosuchname"); + if (pwd || last_error != NSS_STATUS_NOTFOUND) { + total_errors++; + printf("ERROR Non existant user gave error %d\n", last_error); + } + + pwd = getpwuid(0xFFF0); + if (pwd || last_error != NSS_STATUS_NOTFOUND) { + total_errors++; + printf("ERROR Non existant uid gave error %d\n", last_error); + } + + grp = getgrnam("nosuchgroup"); + if (grp || last_error != NSS_STATUS_NOTFOUND) { + total_errors++; + printf("ERROR Non existant group gave error %d\n", last_error); + } + + grp = getgrgid(0xFFF0); + if (grp || last_error != NSS_STATUS_NOTFOUND) { + total_errors++; + printf("ERROR Non existant gid gave error %d\n", last_error); + } +} + + int main(int argc, char *argv[]) +{ + if (argc > 1) so_path = argv[1]; + if (argc > 2) nss_name = argv[2]; + + nss_test_users(); + nss_test_groups(); + nss_test_errors(); + + printf("total_errors=%d\n", total_errors); + + return total_errors; +} diff --git a/nsswitch/nsstest.h b/nsswitch/nsstest.h new file mode 100644 index 0000000000..e69f17c857 --- /dev/null +++ b/nsswitch/nsstest.h @@ -0,0 +1,115 @@ +/* + Unix SMB/CIFS implementation. + nss includes for the nss tester + Copyright (C) Kai Blin 2007 + + 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 3 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, see . +*/ + +#ifndef _NSSTEST_H +#define _NSSTEST_H + +#include +#include + +#ifdef HAVE_NSS_COMMON_H + +/* + * Sun Solaris + */ + +#include +#include +#include + +typedef nss_status_t NSS_STATUS; + +#define NSS_STATUS_SUCCESS NSS_SUCCESS +#define NSS_STATUS_NOTFOUND NSS_NOTFOUND +#define NSS_STATUS_UNAVAIL NSS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN + +#elif HAVE_NSS_H + +/* + * Linux (glibc) + */ + +#include +typedef enum nss_status NSS_STATUS; + +#elif HAVE_NS_API_H + +/* + * SGI IRIX + */ + +#ifdef DATUM +#define _DATUM_DEFINED +#endif + +#include + +typedef enum +{ + NSS_STATUS_SUCCESS=NS_SUCCESS, + NSS_STATUS_NOTFOUND=NS_NOTFOUND, + NSS_STATUS_UNAVAIL=NS_UNAVAIL, + NSS_STATUS_TRYAGAIN=NS_TRYAGAIN +} NSS_STATUS; + +#define NSD_MEM_STATIC 0 +#define NSD_MEM_VOLATILE 1 +#define NSD_MEM_DYNAMIC 2 + +#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) + +/* HP-UX 11 */ + +#include + +#define NSS_STATUS_SUCCESS NSS_SUCCESS +#define NSS_STATUS_NOTFOUND NSS_NOTFOUND +#define NSS_STATUS_UNAVAIL NSS_UNAVAIL +#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN + +#ifdef HAVE_SYNCH_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif + +typedef enum { + NSS_SUCCESS, + NSS_NOTFOUND, + NSS_UNAVAIL, + NSS_TRYAGAIN +} nss_status_t; + +typedef nss_status_t NSS_STATUS; + +#else /* Nothing's defined. Neither solaris nor gnu nor sun nor hp */ + +typedef enum +{ + NSS_STATUS_SUCCESS=0, + NSS_STATUS_NOTFOUND=1, + NSS_STATUS_UNAVAIL=2, + NSS_STATUS_TRYAGAIN=3 +} NSS_STATUS; + +#endif + +#endif /* _NSSTEST_H */ diff --git a/nsswitch/nsstest.m4 b/nsswitch/nsstest.m4 new file mode 100644 index 0000000000..37596489c0 --- /dev/null +++ b/nsswitch/nsstest.m4 @@ -0,0 +1,8 @@ +case "$host_os" in + *linux*) + SMB_ENABLE(nsstest,YES) + ;; + *) + SMB_ENABLE(nsstest,NO) + ;; +esac diff --git a/nsswitch/tests/test_wbinfo.sh b/nsswitch/tests/test_wbinfo.sh new file mode 100755 index 0000000000..4937e7e1a9 --- /dev/null +++ b/nsswitch/tests/test_wbinfo.sh @@ -0,0 +1,186 @@ +#!/bin/sh +# Blackbox test for wbinfo +if [ $# -lt 4 ]; then +cat <. +*/ + +#include "includes.h" +#include "winbind_client.h" +#include "librpc/gen_ndr/ndr_netlogon.h" +#include "libcli/auth/libcli_auth.h" +#include "libcli/security/security.h" +#include "lib/cmdline/popt_common.h" +#include "dynconfig/dynconfig.h" +#include "param/param.h" + +#ifndef fstrcpy +#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1) +#endif + +extern int winbindd_fd; + +static char winbind_separator_int(bool strict) +{ + struct winbindd_response response; + static bool got_sep; + static char sep; + + if (got_sep) + return sep; + + ZERO_STRUCT(response); + + /* Send off request */ + + if (winbindd_request_response(WINBINDD_INFO, NULL, &response) != + NSS_STATUS_SUCCESS) { + d_fprintf(stderr, "could not obtain winbind separator!\n"); + if (strict) { + return 0; + } + /* HACK: (this module should not call lp_ funtions) */ + return *lp_winbind_separator(cmdline_lp_ctx); + } + + sep = response.data.info.winbind_separator; + got_sep = true; + + if (!sep) { + d_fprintf(stderr, "winbind separator was NULL!\n"); + if (strict) { + return 0; + } + /* HACK: (this module should not call lp_ funtions) */ + sep = *lp_winbind_separator(cmdline_lp_ctx); + } + + return sep; +} + +static char winbind_separator(void) +{ + return winbind_separator_int(false); +} + +static const char *get_winbind_domain(void) +{ + struct winbindd_response response; + static fstring winbind_domain; + + ZERO_STRUCT(response); + + /* Send off request */ + + if (winbindd_request_response(WINBINDD_DOMAIN_NAME, NULL, &response) != + NSS_STATUS_SUCCESS) { + d_fprintf(stderr, "could not obtain winbind domain name!\n"); + + /* HACK: (this module should not call lp_ funtions) */ + return lp_workgroup(cmdline_lp_ctx); + } + + fstrcpy(winbind_domain, response.data.domain_name); + + return winbind_domain; + +} + +/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the + form DOMAIN/user into a domain and a user */ + +static bool parse_wbinfo_domain_user(const char *domuser, fstring domain, + fstring user) +{ + + char *p = strchr(domuser,winbind_separator()); + + if (!p) { + fstrcpy(user, domuser); + fstrcpy(domain, get_winbind_domain()); + return true; + } + + fstrcpy(user, p+1); + fstrcpy(domain, domuser); + domain[PTR_DIFF(p, domuser)] = 0; + strupper_m(domain); + + return true; +} + +/* pull pwent info for a given user */ + +static bool wbinfo_get_userinfo(char *user) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.username, user); + + result = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); + + if (result != NSS_STATUS_SUCCESS) + return false; + + d_printf( "%s:%s:%d:%d:%s:%s:%s\n", + response.data.pw.pw_name, + response.data.pw.pw_passwd, + response.data.pw.pw_uid, + response.data.pw.pw_gid, + response.data.pw.pw_gecos, + response.data.pw.pw_dir, + response.data.pw.pw_shell ); + + return true; +} + +/* pull pwent info for a given uid */ +static bool wbinfo_get_uidinfo(int uid) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.uid = uid; + + result = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); + + if (result != NSS_STATUS_SUCCESS) + return false; + + d_printf( "%s:%s:%d:%d:%s:%s:%s\n", + response.data.pw.pw_name, + response.data.pw.pw_passwd, + response.data.pw.pw_uid, + response.data.pw.pw_gid, + response.data.pw.pw_gecos, + response.data.pw.pw_dir, + response.data.pw.pw_shell ); + + return true; +} + +/* pull grent for a given group */ +static bool wbinfo_get_groupinfo(char *group) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.groupname, group); + + result = winbindd_request_response(WINBINDD_GETGRNAM, &request, + &response); + + if ( result != NSS_STATUS_SUCCESS) + return false; + + d_printf( "%s:%s:%d\n", + response.data.gr.gr_name, + response.data.gr.gr_passwd, + response.data.gr.gr_gid ); + + return true; +} + +/* List groups a user is a member of */ + +static bool wbinfo_get_usergroups(char *user) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + int i; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.username, user); + + result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); + + if (result != NSS_STATUS_SUCCESS) + return false; + + for (i = 0; i < response.data.num_entries; i++) + d_printf("%d\n", (int)((gid_t *)response.extra_data.data)[i]); + + SAFE_FREE(response.extra_data.data); + + return true; +} + + +/* List group SIDs a user SID is a member of */ +static bool wbinfo_get_usersids(char *user_sid) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + int i; + const char *s; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + fstrcpy(request.data.sid, user_sid); + + result = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response); + + if (result != NSS_STATUS_SUCCESS) + return false; + + s = (const char *)response.extra_data.data; + for (i = 0; i < response.data.num_entries; i++) { + d_printf("%s\n", s); + s += strlen(s) + 1; + } + + SAFE_FREE(response.extra_data.data); + + return true; +} + +static bool wbinfo_get_userdomgroups(const char *user_sid) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + fstrcpy(request.data.sid, user_sid); + + result = winbindd_request_response(WINBINDD_GETUSERDOMGROUPS, &request, + &response); + + if (result != NSS_STATUS_SUCCESS) + return false; + + if (response.data.num_entries != 0) + printf("%s", (char *)response.extra_data.data); + + SAFE_FREE(response.extra_data.data); + + return true; +} + +/* Convert NetBIOS name to IP */ + +static bool wbinfo_wins_byname(char *name) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.winsreq, name); + + if (winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response) != + NSS_STATUS_SUCCESS) { + return false; + } + + /* Display response */ + + d_printf("%s\n", response.data.winsresp); + + return true; +} + +/* Convert IP to NetBIOS name */ + +static bool wbinfo_wins_byip(char *ip) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.winsreq, ip); + + if (winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response) != + NSS_STATUS_SUCCESS) { + return false; + } + + /* Display response */ + + d_printf("%s\n", response.data.winsresp); + + return true; +} + +/* List trusted domains */ + +static bool wbinfo_list_domains(bool list_all_domains) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + request.data.list_all_domains = list_all_domains; + + if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + if (response.extra_data.data) { + const char *extra_data = (char *)response.extra_data.data; + fstring name; + char *p; + + while(next_token(&extra_data, name, "\n", sizeof(fstring))) { + p = strchr(name, '\\'); + if (p == 0) { + d_fprintf(stderr, "Got invalid response: %s\n", + extra_data); + return false; + } + *p = 0; + d_printf("%s\n", name); + } + + SAFE_FREE(response.extra_data.data); + } + + return true; +} + +/* List own domain */ + +static bool wbinfo_list_own_domain(void) +{ + d_printf("%s\n", get_winbind_domain()); + + return true; +} + +/* show sequence numbers */ +static bool wbinfo_show_sequence(const char *domain) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + if ( domain ) + fstrcpy( request.domain_name, domain ); + + /* Send request */ + + if (winbindd_request_response(WINBINDD_SHOW_SEQUENCE, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + if (response.extra_data.data) { + char *extra_data = (char *)response.extra_data.data; + d_printf("%s", extra_data); + SAFE_FREE(response.extra_data.data); + } + + return true; +} + +/* Show domain info */ + +static bool wbinfo_domain_info(const char *domain_name) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if ((strequal(domain_name, ".")) || (domain_name[0] == '\0')) + fstrcpy(request.domain_name, get_winbind_domain()); + else + fstrcpy(request.domain_name, domain_name); + + /* Send request */ + + if (winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("Name : %s\n", response.data.domain_info.name); + d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name); + + d_printf("SID : %s\n", response.data.domain_info.sid); + + d_printf("Active Directory : %s\n", + response.data.domain_info.active_directory ? "Yes" : "No"); + d_printf("Native : %s\n", + response.data.domain_info.native_mode ? "Yes" : "No"); + + d_printf("Primary : %s\n", + response.data.domain_info.primary ? "Yes" : "No"); + + return true; +} + +/* Get a foreign DC's name */ +static bool wbinfo_getdcname(const char *domain_name) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.domain_name, domain_name); + + /* Send request */ + + if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) != + NSS_STATUS_SUCCESS) { + d_fprintf(stderr, "Could not get dc name for %s\n", domain_name); + return false; + } + + /* Display response */ + + d_printf("%s\n", response.data.dc_name); + + return true; +} + +/* Check trust account password */ + +static bool wbinfo_check_secret(void) +{ + struct winbindd_response response; + NSS_STATUS result; + + ZERO_STRUCT(response); + + result = winbindd_request_response(WINBINDD_CHECK_MACHACC, NULL, &response); + + d_printf("checking the trust secret via RPC calls %s\n", + (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); + + if (result != NSS_STATUS_SUCCESS) + d_fprintf(stderr, "error code was %s (0x%x)\n", + response.data.auth.nt_status_string, + response.data.auth.nt_status); + + return result == NSS_STATUS_SUCCESS; +} + +/* Convert uid to sid */ + +static bool wbinfo_uid_to_sid(uid_t uid) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + request.data.uid = uid; + + if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("%s\n", response.data.sid.sid); + + return true; +} + +/* Convert gid to sid */ + +static bool wbinfo_gid_to_sid(gid_t gid) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + request.data.gid = gid; + + if (winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("%s\n", response.data.sid.sid); + + return true; +} + +/* Convert sid to uid */ + +static bool wbinfo_sid_to_uid(char *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.sid, sid); + + if (winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("%d\n", (int)response.data.uid); + + return true; +} + +static bool wbinfo_sid_to_gid(char *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send request */ + + fstrcpy(request.data.sid, sid); + + if (winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("%d\n", (int)response.data.gid); + + return true; +} + +static const char *sid_type_lookup(enum lsa_SidType r) +{ + switch (r) { + case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break; + case SID_NAME_USER: return "SID_NAME_USER"; break; + case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break; + case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break; + case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break; + case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break; + case SID_NAME_DELETED: return "SID_NAME_DELETED"; break; + case SID_NAME_INVALID: return "SID_NAME_INVALID"; break; + case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break; + case SID_NAME_COMPUTER: return "SID_NAME_COMPUTER"; break; + } + return "Invalid sid type\n"; +} + +/* Convert sid to string */ + +static bool wbinfo_lookupsid(char *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* Send off request */ + + fstrcpy(request.data.sid, sid); + + if (winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("%s%c%s %s\n", response.data.name.dom_name, + winbind_separator(), response.data.name.name, + sid_type_lookup(response.data.name.type)); + + return true; +} + +/* Convert string to sid */ + +static bool wbinfo_lookupname(char *name) +{ + struct winbindd_request request; + struct winbindd_response response; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + parse_wbinfo_domain_user(name, request.data.name.dom_name, + request.data.name.name); + + if (winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Display response */ + + d_printf("%s %s (%d)\n", response.data.sid.sid, sid_type_lookup(response.data.sid.type), response.data.sid.type); + + return true; +} + +/* Authenticate a user with a plaintext password */ + +static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + char *p; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + p = strchr(username, '%'); + + if (p) { + *p = 0; + fstrcpy(request.data.auth.user, username); + fstrcpy(request.data.auth.pass, p + 1); + *p = '%'; + } else + fstrcpy(request.data.auth.user, username); + + request.flags = flags; + + fstrcpy(request.data.auth.krb5_cc_type, cctype); + + request.data.auth.uid = geteuid(); + + result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); + + /* Display response */ + + d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n", + username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype); + + if (response.data.auth.nt_status) + d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", + response.data.auth.nt_status_string, + response.data.auth.nt_status, + response.data.auth.error_string); + + if (result == NSS_STATUS_SUCCESS) { + + if (request.flags & WBFLAG_PAM_INFO3_TEXT) { + if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) { + d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n"); + } + } + + if (response.data.auth.krb5ccname[0] != '\0') { + d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname); + } else { + d_printf("no credentials cached\n"); + } + } + + return result == NSS_STATUS_SUCCESS; +} + +/* Authenticate a user with a plaintext password */ + +static bool wbinfo_auth(char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + char *p; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + p = strchr(username, '%'); + + if (p) { + *p = 0; + fstrcpy(request.data.auth.user, username); + fstrcpy(request.data.auth.pass, p + 1); + *p = '%'; + } else + fstrcpy(request.data.auth.user, username); + + result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); + + /* Display response */ + + d_printf("plaintext password authentication %s\n", + (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); + + if (response.data.auth.nt_status) + d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", + response.data.auth.nt_status_string, + response.data.auth.nt_status, + response.data.auth.error_string); + + return result == NSS_STATUS_SUCCESS; +} + +/* Authenticate a user with a challenge/response */ + +static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + fstring name_user; + fstring name_domain; + fstring pass; + char *p; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + p = strchr(username, '%'); + + if (p) { + *p = 0; + fstrcpy(pass, p + 1); + } + + parse_wbinfo_domain_user(username, name_domain, name_user); + + request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT; + + fstrcpy(request.data.auth_crap.user, name_user); + + fstrcpy(request.data.auth_crap.domain, + name_domain); + + generate_random_buffer(request.data.auth_crap.chal, 8); + + if (lp_client_ntlmv2_auth(lp_ctx)) { + DATA_BLOB server_chal; + DATA_BLOB names_blob; + + DATA_BLOB lm_response; + DATA_BLOB nt_response; + + TALLOC_CTX *mem_ctx; + mem_ctx = talloc_new(NULL); + if (mem_ctx == NULL) { + d_printf("talloc_new failed\n"); + return false; + } + + server_chal = data_blob(request.data.auth_crap.chal, 8); + + /* Pretend this is a login to 'us', for blob purposes */ + names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx)); + + if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal, + &names_blob, + &lm_response, &nt_response, NULL, NULL)) { + data_blob_free(&names_blob); + data_blob_free(&server_chal); + return false; + } + data_blob_free(&names_blob); + data_blob_free(&server_chal); + + memcpy(request.data.auth_crap.nt_resp, nt_response.data, + MIN(nt_response.length, + sizeof(request.data.auth_crap.nt_resp))); + request.data.auth_crap.nt_resp_len = nt_response.length; + + memcpy(request.data.auth_crap.lm_resp, lm_response.data, + MIN(lm_response.length, + sizeof(request.data.auth_crap.lm_resp))); + request.data.auth_crap.lm_resp_len = lm_response.length; + + data_blob_free(&nt_response); + data_blob_free(&lm_response); + + } else { + if (lp_client_lanman_auth(lp_ctx) + && SMBencrypt(pass, request.data.auth_crap.chal, + (unsigned char *)request.data.auth_crap.lm_resp)) { + request.data.auth_crap.lm_resp_len = 24; + } else { + request.data.auth_crap.lm_resp_len = 0; + } + SMBNTencrypt(pass, request.data.auth_crap.chal, + (unsigned char *)request.data.auth_crap.nt_resp); + + request.data.auth_crap.nt_resp_len = 24; + } + + result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response); + + /* Display response */ + + d_printf("challenge/response password authentication %s\n", + (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); + + if (response.data.auth.nt_status) + d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", + response.data.auth.nt_status_string, + response.data.auth.nt_status, + response.data.auth.error_string); + + return result == NSS_STATUS_SUCCESS; +} + +/* Print domain users */ + +static bool print_domain_users(const char *domain) +{ + struct winbindd_request request; + struct winbindd_response response; + const char *extra_data; + fstring name; + + /* Send request to winbind daemon */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (domain) { + /* '.' is the special sign for our own domain */ + if ( strequal(domain, ".") ) + fstrcpy( request.domain_name, get_winbind_domain() ); + else + fstrcpy( request.domain_name, domain ); + } + + if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Look through extra data */ + + if (!response.extra_data.data) + return false; + + extra_data = (const char *)response.extra_data.data; + + while(next_token(&extra_data, name, ",", sizeof(fstring))) + d_printf("%s\n", name); + + SAFE_FREE(response.extra_data.data); + + return true; +} + +/* Print domain groups */ + +static bool print_domain_groups(const char *domain) +{ + struct winbindd_request request; + struct winbindd_response response; + const char *extra_data; + fstring name; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (domain) { + if ( strequal(domain, ".") ) + fstrcpy( request.domain_name, get_winbind_domain() ); + else + fstrcpy( request.domain_name, domain ); + } + + if (winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response) != + NSS_STATUS_SUCCESS) + return false; + + /* Look through extra data */ + + if (!response.extra_data.data) + return false; + + extra_data = (const char *)response.extra_data.data; + + while(next_token(&extra_data, name, ",", sizeof(fstring))) + d_printf("%s\n", name); + + SAFE_FREE(response.extra_data.data); + + return true; +} + +static bool wbinfo_ping(void) +{ + NSS_STATUS result; + + result = winbindd_request_response(WINBINDD_PING, NULL, NULL); + + /* Display response */ + + d_printf("Ping to winbindd %s on fd %d\n", + (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd); + + return result == NSS_STATUS_SUCCESS; +} + +/* Main program */ + +enum { + OPT_SET_AUTH_USER = 1000, + OPT_GET_AUTH_USER, + OPT_DOMAIN_NAME, + OPT_SEQUENCE, + OPT_GETDCNAME, + OPT_USERDOMGROUPS, + OPT_USERSIDS, + OPT_ALLOCATE_UID, + OPT_ALLOCATE_GID, + OPT_SEPARATOR, + OPT_LIST_ALL_DOMAINS, + OPT_LIST_OWN_DOMAIN, + OPT_UID_INFO, + OPT_GROUP_INFO, +}; + +int main(int argc, char **argv, char **envp) +{ + int opt; + + poptContext pc; + static char *string_arg; + static char *opt_domain_name; + static int int_arg; + int result = 1; + + struct poptOption long_options[] = { + POPT_AUTOHELP + + /* longName, shortName, argInfo, argPtr, value, descrip, + argDesc */ + + { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"}, + { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" }, + { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" }, + { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" }, + { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, + { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, + { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, + { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, + { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, + { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, + { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" }, + { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" }, + { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" }, + { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" }, + { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" }, + { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" }, + { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" }, + { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" }, + { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" }, + { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, + { "user-domgroups", 0, POPT_ARG_STRING, &string_arg, + OPT_USERDOMGROUPS, "Get user domain groups", "SID" }, + { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" }, + { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, + { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME, + "Get a DC name for a foreign domain", "domainname" }, + { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, + { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" }, +#ifdef HAVE_KRB5 + { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" }, + /* destroys wbinfo --help output */ + /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */ +#endif + { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL }, + POPT_COMMON_VERSION + POPT_COMMON_SAMBA + POPT_TABLEEND + }; + + /* Parse options */ + + pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0); + + /* Parse command line options */ + + if (argc == 1) { + poptPrintHelp(pc, stderr, 0); + return 1; + } + + while((opt = poptGetNextOpt(pc)) != -1) { + /* get the generic configuration parameters like --domain */ + } + + poptFreeContext(pc); + + pc = poptGetContext(NULL, argc, (const char **)argv, long_options, + POPT_CONTEXT_KEEP_FIRST); + + while((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 'u': + if (!print_domain_users(opt_domain_name)) { + d_fprintf(stderr, "Error looking up domain users\n"); + goto done; + } + break; + case 'g': + if (!print_domain_groups(opt_domain_name)) { + d_fprintf(stderr, "Error looking up domain groups\n"); + goto done; + } + break; + case 's': + if (!wbinfo_lookupsid(string_arg)) { + d_fprintf(stderr, "Could not lookup sid %s\n", string_arg); + goto done; + } + break; + case 'n': + if (!wbinfo_lookupname(string_arg)) { + d_fprintf(stderr, "Could not lookup name %s\n", string_arg); + goto done; + } + break; + case 'N': + if (!wbinfo_wins_byname(string_arg)) { + d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg); + goto done; + } + break; + case 'I': + if (!wbinfo_wins_byip(string_arg)) { + d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg); + goto done; + } + break; + case 'U': + if (!wbinfo_uid_to_sid(int_arg)) { + d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg); + goto done; + } + break; + case 'G': + if (!wbinfo_gid_to_sid(int_arg)) { + d_fprintf(stderr, "Could not convert gid %d to sid\n", + int_arg); + goto done; + } + break; + case 'S': + if (!wbinfo_sid_to_uid(string_arg)) { + d_fprintf(stderr, "Could not convert sid %s to uid\n", + string_arg); + goto done; + } + break; + case 'Y': + if (!wbinfo_sid_to_gid(string_arg)) { + d_fprintf(stderr, "Could not convert sid %s to gid\n", + string_arg); + goto done; + } + break; + case 't': + if (!wbinfo_check_secret()) { + d_fprintf(stderr, "Could not check secret\n"); + goto done; + } + break; + case 'm': + if (!wbinfo_list_domains(false)) { + d_fprintf(stderr, "Could not list trusted domains\n"); + goto done; + } + break; + case OPT_SEQUENCE: + if (!wbinfo_show_sequence(opt_domain_name)) { + d_fprintf(stderr, "Could not show sequence numbers\n"); + goto done; + } + break; + case 'D': + if (!wbinfo_domain_info(string_arg)) { + d_fprintf(stderr, "Could not get domain info\n"); + goto done; + } + break; + case 'i': + if (!wbinfo_get_userinfo(string_arg)) { + d_fprintf(stderr, "Could not get info for user %s\n", + string_arg); + goto done; + } + break; + case OPT_UID_INFO: + if ( !wbinfo_get_uidinfo(int_arg)) { + d_fprintf(stderr, "Could not get info for uid " + "%d\n", int_arg); + goto done; + } + break; + case OPT_GROUP_INFO: + if ( !wbinfo_get_groupinfo(string_arg)) { + d_fprintf(stderr, "Could not get info for " + "group %s\n", string_arg); + goto done; + } + break; + case 'r': + if (!wbinfo_get_usergroups(string_arg)) { + d_fprintf(stderr, "Could not get groups for user %s\n", + string_arg); + goto done; + } + break; + case OPT_USERSIDS: + if (!wbinfo_get_usersids(string_arg)) { + d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", + string_arg); + goto done; + } + break; + case OPT_USERDOMGROUPS: + if (!wbinfo_get_userdomgroups(string_arg)) { + d_fprintf(stderr, "Could not get user's domain groups " + "for user SID %s\n", string_arg); + goto done; + } + break; + case 'a': { + bool got_error = false; + + if (!wbinfo_auth(string_arg)) { + d_fprintf(stderr, "Could not authenticate user %s with " + "plaintext password\n", string_arg); + got_error = true; + } + + if (!wbinfo_auth_crap(cmdline_lp_ctx, string_arg)) { + d_fprintf(stderr, "Could not authenticate user %s with " + "challenge/response\n", string_arg); + got_error = true; + } + + if (got_error) + goto done; + break; + } + case 'K': { + uint32_t flags = WBFLAG_PAM_KRB5 | + WBFLAG_PAM_CACHED_LOGIN | + WBFLAG_PAM_FALLBACK_AFTER_KRB5 | + WBFLAG_PAM_INFO3_TEXT; + + if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) { + d_fprintf(stderr, "Could not authenticate user [%s] with " + "Kerberos (ccache: %s)\n", string_arg, "FILE"); + goto done; + } + break; + } + case 'p': + if (!wbinfo_ping()) { + d_fprintf(stderr, "could not ping winbindd!\n"); + goto done; + } + break; + case OPT_GETDCNAME: + if (!wbinfo_getdcname(string_arg)) { + goto done; + } + break; + case OPT_SEPARATOR: { + const char sep = winbind_separator_int(true); + if ( !sep ) { + goto done; + } + d_printf("%c\n", sep); + break; + } + case OPT_LIST_ALL_DOMAINS: + if (!wbinfo_list_domains(true)) { + goto done; + } + break; + case OPT_LIST_OWN_DOMAIN: + if (!wbinfo_list_own_domain()) { + goto done; + } + break; + /* generic configuration options */ + case OPT_DOMAIN_NAME: + break; + default: + d_fprintf(stderr, "Invalid option\n"); + poptPrintHelp(pc, stderr, 0); + goto done; + } + } + + result = 0; + + /* Exit code */ + + done: + poptFreeContext(pc); + return result; +} diff --git a/source3/samba4.m4 b/source3/samba4.m4 index 9ef3d71fd0..34d03de158 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -35,7 +35,7 @@ m4_include(../lib/util/time.m4) m4_include(../lib/popt/samba.m4) m4_include(../lib/util/charset/config.m4) m4_include(lib/socket/config.m4) -m4_include(nsswitch/nsstest.m4) +m4_include(../nsswitch/nsstest.m4) m4_include(../pidl/config.m4) AC_ZLIB([ SMB_EXT_LIB(ZLIB, [${ZLIB_LIBS}]) @@ -119,7 +119,7 @@ m4_include(ntvfs/unixuid/config.m4) m4_include(auth/config.m4) m4_include(kdc/config.m4) m4_include(ntvfs/sysdep/config.m4) -m4_include(nsswitch/config.m4) +m4_include(../nsswitch/config.m4) dnl Samba 4 files AC_SUBST(LD) diff --git a/source3/samba4.mk b/source3/samba4.mk index 38d1ec2e19..18f7541333 100644 --- a/source3/samba4.mk +++ b/source3/samba4.mk @@ -70,7 +70,7 @@ smbdsrcdir := $(samba4srcdir)/smbd clustersrcdir := $(samba4srcdir)/cluster libnetsrcdir := $(samba4srcdir)/libnet authsrcdir := $(samba4srcdir)/auth -nsswitchsrcdir := $(samba4srcdir)/nsswitch +nsswitchsrcdir := $(samba4srcdir)/../nsswitch libsrcdir := $(samba4srcdir)/lib libsocketsrcdir := $(samba4srcdir)/lib/socket libcharsetsrcdir := $(samba4srcdir)/../lib/util/charset @@ -161,7 +161,7 @@ modules:: $(PLUGINS) pythonmods:: $(PYTHON_PYS) $(PYTHON_SO) -all:: bin/samba4 bin/regpatch4 bin/regdiff4 bin/regshell4 bin/regtree4 bin/smbclient4 pythonmods setup +all:: bin/samba4 bin/regpatch4 bin/regdiff4 bin/regshell4 bin/regtree4 bin/smbclient4 bin/wbinfo4 pythonmods setup torture:: bin/smbtorture4 everything:: $(patsubst %,%4,$(BINARIES)) setup: diff --git a/source4/Makefile b/source4/Makefile index 38eb0706c9..8899cde2d2 100644 --- a/source4/Makefile +++ b/source4/Makefile @@ -56,7 +56,7 @@ smbdsrcdir := smbd clustersrcdir := cluster libnetsrcdir := libnet authsrcdir := auth -nsswitchsrcdir := nsswitch +nsswitchsrcdir := ../nsswitch libsrcdir := lib libsocketsrcdir := lib/socket libcharsetsrcdir := ../lib/util/charset diff --git a/source4/configure.ac b/source4/configure.ac index a90ac9e668..53e093e813 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -30,7 +30,7 @@ SMB_EXT_LIB(ZLIB, [${ZLIB_LIBS}]) ],[ SMB_INCLUDE_MK(lib/zlib.mk) ]) -m4_include(nsswitch/nsstest.m4) +m4_include(../nsswitch/nsstest.m4) m4_include(../pidl/config.m4) AC_CONFIG_FILES(lib/registry/registry.pc) @@ -108,7 +108,7 @@ m4_include(../lib/nss_wrapper/config.m4) m4_include(auth/config.m4) m4_include(kdc/config.m4) m4_include(ntvfs/sysdep/config.m4) -m4_include(nsswitch/config.m4) +m4_include(../nsswitch/config.m4) ################################################# # add *_CFLAGS only for the real build diff --git a/source4/main.mk b/source4/main.mk index 0a72487f8a..1d4ffc5d44 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -6,7 +6,7 @@ mkinclude cluster/config.mk mkinclude smbd/process_model.mk mkinclude libnet/config.mk mkinclude auth/config.mk -mkinclude nsswitch/config.mk +mkinclude ../nsswitch/config.mk mkinclude lib/samba3/config.mk mkinclude lib/socket/config.mk mkinclude ../lib/util/charset/config.mk diff --git a/source4/nsswitch/config.m4 b/source4/nsswitch/config.m4 deleted file mode 100644 index 207b7fa53f..0000000000 --- a/source4/nsswitch/config.m4 +++ /dev/null @@ -1,12 +0,0 @@ -AC_CHECK_HEADERS(nss.h nss_common.h ns_api.h ) - -case "$host_os" in - *linux*) - SMB_LIBRARY(nss_winbind, - [nsswitch/winbind_nss_linux.o], - [LIBWINBIND-CLIENT]) - ;; - *) - ;; -esac - diff --git a/source4/nsswitch/config.mk b/source4/nsswitch/config.mk deleted file mode 100644 index e8b9600882..0000000000 --- a/source4/nsswitch/config.mk +++ /dev/null @@ -1,34 +0,0 @@ -[SUBSYSTEM::LIBWINBIND-CLIENT] -PRIVATE_DEPENDENCIES = SOCKET_WRAPPER - -LIBWINBIND-CLIENT_OBJ_FILES = $(nsswitchsrcdir)/wb_common.o - -################################# -# Start BINARY nsstest -[BINARY::nsstest] -INSTALLDIR = BINDIR -PRIVATE_DEPENDENCIES = \ - LIBSAMBA-UTIL \ - LIBREPLACE_EXT \ - LIBSAMBA-HOSTCONFIG -# End BINARY nsstest -################################# - -nsstest_OBJ_FILES = $(nsswitchsrcdir)/nsstest.o - -################################# -# Start BINARY wbinfo -[BINARY::wbinfo] -INSTALLDIR = BINDIR -PRIVATE_DEPENDENCIES = \ - LIBSAMBA-UTIL \ - LIBREPLACE_EXT \ - LIBCLI_AUTH \ - LIBPOPT \ - POPT_SAMBA \ - LIBWINBIND-CLIENT -# End BINARY nsstest -################################# - -wbinfo_OBJ_FILES = \ - $(nsswitchsrcdir)/wbinfo.o diff --git a/source4/nsswitch/nsstest.c b/source4/nsswitch/nsstest.c deleted file mode 100644 index df7f33f8e0..0000000000 --- a/source4/nsswitch/nsstest.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - Unix SMB/CIFS implementation. - nss tester for winbindd - Copyright (C) Andrew Tridgell 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 3 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, see . -*/ - -#include "includes.h" - -#include "nsswitch/nsstest.h" - -static const char *so_path = "/lib/libnss_winbind.so"; -static const char *nss_name = "winbind"; -static int nss_errno; -static NSS_STATUS last_error; -static int total_errors; - -static void *find_fn(const char *name) -{ - char s[1024]; - static void *h; - void *res; - - snprintf(s,sizeof(s), "_nss_%s_%s", nss_name, name); - - if (!h) { - h = dlopen(so_path, RTLD_LAZY); - } - if (!h) { - printf("Can't open shared library %s\n", so_path); - exit(1); - } - res = dlsym(h, s); - if (!res) { - printf("Can't find function %s\n", s); - return NULL; - } - return res; -} - -static void report_nss_error(const char *who, NSS_STATUS status) -{ - last_error = status; - total_errors++; - printf("ERROR %s: NSS_STATUS=%d %d (nss_errno=%d)\n", - who, status, NSS_STATUS_SUCCESS, nss_errno); -} - -static struct passwd *nss_getpwent(void) -{ - NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, - size_t , int *) = find_fn("getpwent_r"); - static struct passwd pwd; - static char buf[1000]; - NSS_STATUS status; - - status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno); - if (status == NSS_STATUS_NOTFOUND) { - return NULL; - } - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("getpwent", status); - return NULL; - } - return &pwd; -} - -static struct passwd *nss_getpwnam(const char *name) -{ - NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, - size_t , int *) = find_fn("getpwnam_r"); - static struct passwd pwd; - static char buf[1000]; - NSS_STATUS status; - - status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno); - if (status == NSS_STATUS_NOTFOUND) { - return NULL; - } - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("getpwnam", status); - return NULL; - } - return &pwd; -} - -static struct passwd *nss_getpwuid(uid_t uid) -{ - NSS_STATUS (*_nss_getpwuid_r)(uid_t , struct passwd *, char *, - size_t , int *) = find_fn("getpwuid_r"); - static struct passwd pwd; - static char buf[1000]; - NSS_STATUS status; - - status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno); - if (status == NSS_STATUS_NOTFOUND) { - return NULL; - } - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("getpwuid", status); - return NULL; - } - return &pwd; -} - -static void nss_setpwent(void) -{ - NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent"); - NSS_STATUS status; - status = _nss_setpwent(); - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("setpwent", status); - } -} - -static void nss_endpwent(void) -{ - NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent"); - NSS_STATUS status; - status = _nss_endpwent(); - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("endpwent", status); - } -} - - -static struct group *nss_getgrent(void) -{ - NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, - size_t , int *) = find_fn("getgrent_r"); - static struct group grp; - static char *buf; - static int buflen = 1024; - NSS_STATUS status; - - if (!buf) buf = malloc_array_p(char, buflen); - -again: - status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno); - if (status == NSS_STATUS_TRYAGAIN) { - buflen *= 2; - buf = realloc_p(buf, char, buflen); - goto again; - } - if (status == NSS_STATUS_NOTFOUND) { - return NULL; - } - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("getgrent", status); - return NULL; - } - return &grp; -} - -static struct group *nss_getgrnam(const char *name) -{ - NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, - size_t , int *) = find_fn("getgrnam_r"); - static struct group grp; - static char *buf; - static int buflen = 1000; - NSS_STATUS status; - - if (!buf) buf = malloc_array_p(char, buflen); -again: - status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno); - if (status == NSS_STATUS_TRYAGAIN) { - buflen *= 2; - buf = realloc_p(buf, char, buflen); - goto again; - } - if (status == NSS_STATUS_NOTFOUND) { - return NULL; - } - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("getgrnam", status); - return NULL; - } - return &grp; -} - -static struct group *nss_getgrgid(gid_t gid) -{ - NSS_STATUS (*_nss_getgrgid_r)(gid_t , struct group *, char *, - size_t , int *) = find_fn("getgrgid_r"); - static struct group grp; - static char *buf; - static int buflen = 1000; - NSS_STATUS status; - - if (!buf) buf = malloc_array_p(char, buflen); -again: - status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno); - if (status == NSS_STATUS_TRYAGAIN) { - buflen *= 2; - buf = realloc_p(buf, char, buflen); - goto again; - } - if (status == NSS_STATUS_NOTFOUND) { - return NULL; - } - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("getgrgid", status); - return NULL; - } - return &grp; -} - -static void nss_setgrent(void) -{ - NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent"); - NSS_STATUS status; - status = _nss_setgrent(); - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("setgrent", status); - } -} - -static void nss_endgrent(void) -{ - NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent"); - NSS_STATUS status; - status = _nss_endgrent(); - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("endgrent", status); - } -} - -static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *start, long int *size) -{ - NSS_STATUS (*_nss_initgroups)(char *, gid_t , long int *, - long int *, gid_t **, long int , int *) = - find_fn("initgroups_dyn"); - NSS_STATUS status; - - if (!_nss_initgroups) return NSS_STATUS_UNAVAIL; - - status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno); - if (status != NSS_STATUS_SUCCESS) { - report_nss_error("initgroups", status); - } - return status; -} - -static void print_passwd(struct passwd *pwd) -{ - printf("%s:%s:%d:%d:%s:%s:%s\n", - pwd->pw_name, - pwd->pw_passwd, - pwd->pw_uid, - pwd->pw_gid, - pwd->pw_gecos, - pwd->pw_dir, - pwd->pw_shell); -} - -static void print_group(struct group *grp) -{ - int i; - printf("%s:%s:%d: ", - grp->gr_name, - grp->gr_passwd, - grp->gr_gid); - - if (!grp->gr_mem[0]) { - printf("\n"); - return; - } - - for (i=0; grp->gr_mem[i+1]; i++) { - printf("%s, ", grp->gr_mem[i]); - } - printf("%s\n", grp->gr_mem[i]); -} - -static void nss_test_initgroups(char *name, gid_t gid) -{ - long int size = 16; - long int start = 1; - gid_t *groups = NULL; - int i; - NSS_STATUS status; - - groups = (gid_t *)malloc_array_p(gid_t, size); - groups[0] = gid; - - status = nss_initgroups(name, gid, &groups, &start, &size); - if (status == NSS_STATUS_UNAVAIL) { - printf("No initgroups fn\n"); - return; - } - - for (i=0; ipw_name); - printf("getpwent: "); print_passwd(pwd); - pwd = nss_getpwuid(pwd->pw_uid); - if (!pwd) { - total_errors++; - printf("ERROR: can't getpwuid\n"); - continue; - } - printf("getpwuid: "); print_passwd(pwd); - pwd = nss_getpwnam(pwd->pw_name); - if (!pwd) { - total_errors++; - printf("ERROR: can't getpwnam\n"); - continue; - } - printf("getpwnam: "); print_passwd(pwd); - printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid); - printf("\n"); - } - nss_endpwent(); -} - -static void nss_test_groups(void) -{ - struct group *grp; - - nss_setgrent(); - /* loop over all groups */ - while ((grp = nss_getgrent())) { - printf("Testing group %s\n", grp->gr_name); - printf("getgrent: "); print_group(grp); - grp = nss_getgrnam(grp->gr_name); - if (!grp) { - total_errors++; - printf("ERROR: can't getgrnam\n"); - continue; - } - printf("getgrnam: "); print_group(grp); - grp = nss_getgrgid(grp->gr_gid); - if (!grp) { - total_errors++; - printf("ERROR: can't getgrgid\n"); - continue; - } - printf("getgrgid: "); print_group(grp); - printf("\n"); - } - nss_endgrent(); -} - -static void nss_test_errors(void) -{ - struct passwd *pwd; - struct group *grp; - - pwd = getpwnam("nosuchname"); - if (pwd || last_error != NSS_STATUS_NOTFOUND) { - total_errors++; - printf("ERROR Non existant user gave error %d\n", last_error); - } - - pwd = getpwuid(0xFFF0); - if (pwd || last_error != NSS_STATUS_NOTFOUND) { - total_errors++; - printf("ERROR Non existant uid gave error %d\n", last_error); - } - - grp = getgrnam("nosuchgroup"); - if (grp || last_error != NSS_STATUS_NOTFOUND) { - total_errors++; - printf("ERROR Non existant group gave error %d\n", last_error); - } - - grp = getgrgid(0xFFF0); - if (grp || last_error != NSS_STATUS_NOTFOUND) { - total_errors++; - printf("ERROR Non existant gid gave error %d\n", last_error); - } -} - - int main(int argc, char *argv[]) -{ - if (argc > 1) so_path = argv[1]; - if (argc > 2) nss_name = argv[2]; - - nss_test_users(); - nss_test_groups(); - nss_test_errors(); - - printf("total_errors=%d\n", total_errors); - - return total_errors; -} diff --git a/source4/nsswitch/nsstest.h b/source4/nsswitch/nsstest.h deleted file mode 100644 index 599faf2ee2..0000000000 --- a/source4/nsswitch/nsstest.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - Unix SMB/CIFS implementation. - nss includes for the nss tester - Copyright (C) Kai Blin 2007 - - 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 3 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, see . -*/ - -#ifndef _NSSTEST_H -#define _NSSTEST_H - -#include -#include - -#ifdef HAVE_NSS_COMMON_H - -/* - * Sun Solaris - */ - -#include -#include -#include - -typedef nss_status_t NSS_STATUS; - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -#elif HAVE_NSS_H - -/* - * Linux (glibc) - */ - -#include -typedef enum nss_status NSS_STATUS; - -#elif HAVE_NS_API_H - -/* - * SGI IRIX - */ - -#ifdef DATUM -#define _DATUM_DEFINED -#endif - -#include - -typedef enum -{ - NSS_STATUS_SUCCESS=NS_SUCCESS, - NSS_STATUS_NOTFOUND=NS_NOTFOUND, - NSS_STATUS_UNAVAIL=NS_UNAVAIL, - NSS_STATUS_TRYAGAIN=NS_TRYAGAIN -} NSS_STATUS; - -#define NSD_MEM_STATIC 0 -#define NSD_MEM_VOLATILE 1 -#define NSD_MEM_DYNAMIC 2 - -#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) - -/* HP-UX 11 */ - -#include - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -#ifdef HAVE_SYNCH_H -#include -#endif -#ifdef HAVE_PTHREAD_H -#include -#endif - -typedef enum { - NSS_SUCCESS, - NSS_NOTFOUND, - NSS_UNAVAIL, - NSS_TRYAGAIN -} nss_status_t; - -typedef nss_status_t NSS_STATUS; - -#else /* Nothing's defined. Neither solaris nor gnu nor sun nor hp */ - -typedef enum -{ - NSS_STATUS_SUCCESS=0, - NSS_STATUS_NOTFOUND=1, - NSS_STATUS_UNAVAIL=2, - NSS_STATUS_TRYAGAIN=3 -} NSS_STATUS; - -#endif - -#endif /* _NSSTEST_H */ diff --git a/source4/nsswitch/nsstest.m4 b/source4/nsswitch/nsstest.m4 deleted file mode 100644 index 2856f9de15..0000000000 --- a/source4/nsswitch/nsstest.m4 +++ /dev/null @@ -1,9 +0,0 @@ -case "$host_os" in - *linux*) - SMB_ENABLE(nsstest,YES) - ;; - *) - SMB_ENABLE(nsstest,NO) - ;; -esac - diff --git a/source4/nsswitch/tests/test_wbinfo.sh b/source4/nsswitch/tests/test_wbinfo.sh deleted file mode 100755 index a67fac9394..0000000000 --- a/source4/nsswitch/tests/test_wbinfo.sh +++ /dev/null @@ -1,187 +0,0 @@ -#!/bin/sh -# Blackbox test for wbinfo -if [ $# -lt 4 ]; then -cat <. -*/ - -#include "winbind_client.h" - -/* Global variables. These are effectively the client state information */ - -int winbindd_fd = -1; /* fd for winbindd socket */ -static int is_privileged = 0; - -/* Free a response structure */ - -void winbindd_free_response(struct winbindd_response *response) -{ - /* Free any allocated extra_data */ - - if (response) - SAFE_FREE(response->extra_data.data); -} - -/* Initialise a request structure */ - -void winbindd_init_request(struct winbindd_request *request, int request_type) -{ - request->length = sizeof(struct winbindd_request); - - request->cmd = (enum winbindd_cmd)request_type; - request->pid = getpid(); - -} - -/* Initialise a response structure */ - -static void init_response(struct winbindd_response *response) -{ - /* Initialise return value */ - - response->result = WINBINDD_ERROR; -} - -/* Close established socket */ - -void winbind_close_sock(void) -{ - if (winbindd_fd != -1) { - close(winbindd_fd); - winbindd_fd = -1; - } -} - -#define CONNECT_TIMEOUT 30 - -/* Make sure socket handle isn't stdin, stdout or stderr */ -#define RECURSION_LIMIT 3 - -static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) -{ - int new_fd; - if (fd >= 0 && fd <= 2) { -#ifdef F_DUPFD - if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { - return -1; - } - /* Paranoia */ - if (new_fd < 3) { - close(new_fd); - return -1; - } - close(fd); - return new_fd; -#else - if (limit <= 0) - return -1; - - new_fd = dup(fd); - if (new_fd == -1) - return -1; - - /* use the program stack to hold our list of FDs to close */ - new_fd = make_nonstd_fd_internals(new_fd, limit - 1); - close(fd); - return new_fd; -#endif - } - return fd; -} - -/**************************************************************************** - Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, - else - if SYSV use O_NDELAY - if BSD use FNDELAY - Set close on exec also. -****************************************************************************/ - -static int make_safe_fd(int fd) -{ - int result, flags; - int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); - if (new_fd == -1) { - close(fd); - return -1; - } - - /* Socket should be nonblocking. */ -#ifdef O_NONBLOCK -#define FLAG_TO_SET O_NONBLOCK -#else -#ifdef SYSV -#define FLAG_TO_SET O_NDELAY -#else /* BSD */ -#define FLAG_TO_SET FNDELAY -#endif -#endif - - if ((flags = fcntl(new_fd, F_GETFL)) == -1) { - close(new_fd); - return -1; - } - - flags |= FLAG_TO_SET; - if (fcntl(new_fd, F_SETFL, flags) == -1) { - close(new_fd); - return -1; - } - -#undef FLAG_TO_SET - - /* Socket should be closed on exec() */ -#ifdef FD_CLOEXEC - result = flags = fcntl(new_fd, F_GETFD, 0); - if (flags >= 0) { - flags |= FD_CLOEXEC; - result = fcntl( new_fd, F_SETFD, flags ); - } - if (result < 0) { - close(new_fd); - return -1; - } -#endif - return new_fd; -} - -/* Connect to winbindd socket */ - -static int winbind_named_pipe_sock(const char *dir) -{ - struct sockaddr_un sunaddr; - struct stat st; - char *path; - int fd; - int wait_time; - int slept; - - /* Check permissions on unix socket directory */ - - if (lstat(dir, &st) == -1) { - return -1; - } - - if (!S_ISDIR(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - return -1; - } - - /* Connect to socket */ - - asprintf(&path, "%s/%s", dir, WINBINDD_SOCKET_NAME); - - ZERO_STRUCT(sunaddr); - sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); - SAFE_FREE(path); - - /* If socket file doesn't exist, don't bother trying to connect - with retry. This is an attempt to make the system usable when - the winbindd daemon is not running. */ - - if (lstat(sunaddr.sun_path, &st) == -1) { - return -1; - } - - /* Check permissions on unix socket file */ - - if (!S_ISSOCK(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - return -1; - } - - /* Connect to socket */ - - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return -1; - } - - /* Set socket non-blocking and close on exec. */ - - if ((fd = make_safe_fd( fd)) == -1) { - return fd; - } - - for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1; - wait_time += slept) { - struct timeval tv; - fd_set w_fds; - int ret; - int connect_errno = 0; - socklen_t errnosize; - - if (wait_time >= CONNECT_TIMEOUT) - goto error_out; - - switch (errno) { - case EINPROGRESS: - FD_ZERO(&w_fds); - FD_SET(fd, &w_fds); - tv.tv_sec = CONNECT_TIMEOUT - wait_time; - tv.tv_usec = 0; - - ret = select(fd + 1, NULL, &w_fds, NULL, &tv); - - if (ret > 0) { - errnosize = sizeof(connect_errno); - - ret = getsockopt(fd, SOL_SOCKET, - SO_ERROR, &connect_errno, &errnosize); - - if (ret >= 0 && connect_errno == 0) { - /* Connect succeed */ - goto out; - } - } - - slept = CONNECT_TIMEOUT; - break; - case EAGAIN: - slept = rand() % 3 + 1; - sleep(slept); - break; - default: - goto error_out; - } - - } - - out: - - return fd; - - error_out: - - close(fd); - return -1; -} - -static const char *winbindd_socket_dir(void) -{ -#ifdef SOCKET_WRAPPER - const char *env_dir; - - env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); - if (env_dir) { - return env_dir; - } -#endif - - return WINBINDD_SOCKET_DIR; -} - -/* Connect to winbindd socket */ - -static int winbind_open_pipe_sock(int recursing, int need_priv) -{ -#ifdef HAVE_UNIXSOCKET - static pid_t our_pid; - struct winbindd_request request; - struct winbindd_response response; - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (our_pid != getpid()) { - winbind_close_sock(); - our_pid = getpid(); - } - - if ((need_priv != 0) && (is_privileged == 0)) { - winbind_close_sock(); - } - - if (winbindd_fd != -1) { - return winbindd_fd; - } - - if (recursing) { - return -1; - } - - if ((winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir())) == -1) { - return -1; - } - - is_privileged = 0; - - /* version-check the socket */ - - request.wb_flags = WBFLAG_RECURSE; - if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { - winbind_close_sock(); - return -1; - } - - /* try and get priv pipe */ - - request.wb_flags = WBFLAG_RECURSE; - if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { - int fd; - if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) { - close(winbindd_fd); - winbindd_fd = fd; - is_privileged = 1; - } - } - - if ((need_priv != 0) && (is_privileged == 0)) { - return -1; - } - - SAFE_FREE(response.extra_data.data); - - return winbindd_fd; -#else - return -1; -#endif /* HAVE_UNIXSOCKET */ -} - -/* Write data to winbindd socket */ - -int winbind_write_sock(void *buffer, int count, int recursing, int need_priv) -{ - int result, nwritten; - - /* Open connection to winbind daemon */ - - restart: - - if (winbind_open_pipe_sock(recursing, need_priv) == -1) { - return -1; - } - - /* Write data to socket */ - - nwritten = 0; - - while(nwritten < count) { - struct timeval tv; - fd_set r_fds; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(winbindd_fd, &r_fds); - ZERO_STRUCT(tv); - - if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { - winbind_close_sock(); - return -1; /* Select error */ - } - - /* Write should be OK if fd not available for reading */ - - if (!FD_ISSET(winbindd_fd, &r_fds)) { - - /* Do the write */ - - result = write(winbindd_fd, - (char *)buffer + nwritten, - count - nwritten); - - if ((result == -1) || (result == 0)) { - - /* Write failed */ - - winbind_close_sock(); - return -1; - } - - nwritten += result; - - } else { - - /* Pipe has closed on remote end */ - - winbind_close_sock(); - goto restart; - } - } - - return nwritten; -} - -/* Read data from winbindd socket */ - -int winbind_read_sock(void *buffer, int count) -{ - int nread = 0; - int total_time = 0, selret; - - if (winbindd_fd == -1) { - return -1; - } - - /* Read data from socket */ - while(nread < count) { - struct timeval tv; - fd_set r_fds; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(winbindd_fd, &r_fds); - ZERO_STRUCT(tv); - /* Wait for 5 seconds for a reply. May need to parameterise this... */ - tv.tv_sec = 5; - - if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) { - winbind_close_sock(); - return -1; /* Select error */ - } - - if (selret == 0) { - /* Not ready for read yet... */ - if (total_time >= 30) { - /* Timeout */ - winbind_close_sock(); - return -1; - } - total_time += 5; - continue; - } - - if (FD_ISSET(winbindd_fd, &r_fds)) { - - /* Do the Read */ - - int result = read(winbindd_fd, (char *)buffer + nread, - count - nread); - - if ((result == -1) || (result == 0)) { - - /* Read failed. I think the only useful thing we - can do here is just return -1 and fail since the - transaction has failed half way through. */ - - winbind_close_sock(); - return -1; - } - - nread += result; - - } - } - - return nread; -} - -/* Read reply */ - -int winbindd_read_reply(struct winbindd_response *response) -{ - int result1, result2 = 0; - - if (!response) { - return -1; - } - - /* Read fixed length response */ - - result1 = winbind_read_sock(response, - sizeof(struct winbindd_response)); - if (result1 == -1) { - return -1; - } - - /* We actually send the pointer value of the extra_data field from - the server. This has no meaning in the client's address space - so we clear it out. */ - - response->extra_data.data = NULL; - - /* Read variable length response */ - - if (response->length > sizeof(struct winbindd_response)) { - int extra_data_len = response->length - - sizeof(struct winbindd_response); - - /* Mallocate memory for extra data */ - - if (!(response->extra_data.data = malloc(extra_data_len))) { - return -1; - } - - result2 = winbind_read_sock(response->extra_data.data, - extra_data_len); - if (result2 == -1) { - winbindd_free_response(response); - return -1; - } - } - - /* Return total amount of data read */ - - return result1 + result2; -} - -bool winbind_env_set(void) -{ - char *env; - - if ((env=getenv(WINBINDD_DONT_ENV)) != NULL) { - if(strcmp(env, "1") == 0) { - return true; - } - } - return false; -} - -/* - * send simple types of requests - */ - -NSS_STATUS winbindd_send_request(int req_type, int need_priv, - struct winbindd_request *request) -{ - struct winbindd_request lrequest; - - /* Check for our tricky environment variable */ - - if (winbind_env_set()) { - return NSS_STATUS_NOTFOUND; - } - - if (!request) { - ZERO_STRUCT(lrequest); - request = &lrequest; - } - - /* Fill in request and send down pipe */ - - winbindd_init_request(request, req_type); - - if (winbind_write_sock(request, sizeof(*request), - request->wb_flags & WBFLAG_RECURSE, - need_priv) == -1) { - return NSS_STATUS_UNAVAIL; - } - - if ((request->extra_len != 0) && - (winbind_write_sock(request->extra_data.data, - request->extra_len, - request->wb_flags & WBFLAG_RECURSE, - need_priv) == -1)) { - return NSS_STATUS_UNAVAIL; - } - - return NSS_STATUS_SUCCESS; -} - -/* - * Get results from winbindd request - */ - -NSS_STATUS winbindd_get_response(struct winbindd_response *response) -{ - struct winbindd_response lresponse; - - if (!response) { - ZERO_STRUCT(lresponse); - response = &lresponse; - } - - init_response(response); - - /* Wait for reply */ - if (winbindd_read_reply(response) == -1) { - return NSS_STATUS_UNAVAIL; - } - - /* Throw away extra data if client didn't request it */ - if (response == &lresponse) { - winbindd_free_response(response); - } - - /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - return NSS_STATUS_NOTFOUND; - } - - return NSS_STATUS_SUCCESS; -} - -/* Handle simple types of requests */ - -NSS_STATUS winbindd_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - NSS_STATUS status = NSS_STATUS_UNAVAIL; - int count = 0; - - while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { - status = winbindd_send_request(req_type, 0, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - status = winbindd_get_response(response); - count += 1; - } - - return status; -} - -NSS_STATUS winbindd_priv_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - NSS_STATUS status = NSS_STATUS_UNAVAIL; - int count = 0; - - while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { - status = winbindd_send_request(req_type, 1, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - status = winbindd_get_response(response); - count += 1; - } - - return status; -} - -/************************************************************************* - A couple of simple functions to disable winbindd lookups and re- - enable them - ************************************************************************/ - -bool winbind_off(void) -{ - return setenv(WINBINDD_DONT_ENV, "1", 1) != -1; -} - -bool winbind_on(void) -{ - return setenv(WINBINDD_DONT_ENV, "0", 1) != -1; -} - -/************************************************************************* - ************************************************************************/ - -const char *nss_err_str(NSS_STATUS ret) -{ - switch (ret) { - case NSS_STATUS_TRYAGAIN: - return "NSS_STATUS_TRYAGAIN"; - case NSS_STATUS_SUCCESS: - return "NSS_STATUS_SUCCESS"; - case NSS_STATUS_NOTFOUND: - return "NSS_STATUS_NOTFOUND"; - case NSS_STATUS_UNAVAIL: - return "NSS_STATUS_UNAVAIL"; -#ifdef NSS_STATUS_RETURN - case NSS_STATUS_RETURN: - return "NSS_STATUS_RETURN"; -#endif - default: - return "UNKNOWN RETURN CODE!!!!!!!"; - } -} diff --git a/source4/nsswitch/wbinfo.c b/source4/nsswitch/wbinfo.c deleted file mode 100644 index 60c95a3bd0..0000000000 --- a/source4/nsswitch/wbinfo.c +++ /dev/null @@ -1,1290 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind status program. - - Copyright (C) Tim Potter 2000-2003 - Copyright (C) Andrew Bartlett 2002-2007 - - 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 3 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, see . -*/ - -#include "includes.h" -#include "winbind_client.h" -#include "librpc/gen_ndr/ndr_netlogon.h" -#include "libcli/auth/libcli_auth.h" -#include "libcli/security/security.h" -#include "lib/cmdline/popt_common.h" -#include "dynconfig/dynconfig.h" -#include "param/param.h" - -extern int winbindd_fd; - -static char winbind_separator_int(bool strict) -{ - struct winbindd_response response; - static bool got_sep; - static char sep; - - if (got_sep) - return sep; - - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request_response(WINBINDD_INFO, NULL, &response) != - NSS_STATUS_SUCCESS) { - d_fprintf(stderr, "could not obtain winbind separator!\n"); - if (strict) { - return 0; - } - /* HACK: (this module should not call lp_ funtions) */ - return *lp_winbind_separator(cmdline_lp_ctx); - } - - sep = response.data.info.winbind_separator; - got_sep = true; - - if (!sep) { - d_fprintf(stderr, "winbind separator was NULL!\n"); - if (strict) { - return 0; - } - /* HACK: (this module should not call lp_ funtions) */ - sep = *lp_winbind_separator(cmdline_lp_ctx); - } - - return sep; -} - -static char winbind_separator(void) -{ - return winbind_separator_int(false); -} - -static const char *get_winbind_domain(void) -{ - struct winbindd_response response; - static fstring winbind_domain; - - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request_response(WINBINDD_DOMAIN_NAME, NULL, &response) != - NSS_STATUS_SUCCESS) { - d_fprintf(stderr, "could not obtain winbind domain name!\n"); - - /* HACK: (this module should not call lp_ funtions) */ - return lp_workgroup(cmdline_lp_ctx); - } - - fstrcpy(winbind_domain, response.data.domain_name); - - return winbind_domain; - -} - -/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the - form DOMAIN/user into a domain and a user */ - -static bool parse_wbinfo_domain_user(const char *domuser, fstring domain, - fstring user) -{ - - char *p = strchr(domuser,winbind_separator()); - - if (!p) { - fstrcpy(user, domuser); - fstrcpy(domain, get_winbind_domain()); - return true; - } - - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - strupper_m(domain); - - return true; -} - -/* pull pwent info for a given user */ - -static bool wbinfo_get_userinfo(char *user) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.username, user); - - result = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); - - if (result != NSS_STATUS_SUCCESS) - return false; - - d_printf( "%s:%s:%d:%d:%s:%s:%s\n", - response.data.pw.pw_name, - response.data.pw.pw_passwd, - response.data.pw.pw_uid, - response.data.pw.pw_gid, - response.data.pw.pw_gecos, - response.data.pw.pw_dir, - response.data.pw.pw_shell ); - - return true; -} - -/* pull pwent info for a given uid */ -static bool wbinfo_get_uidinfo(int uid) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.uid = uid; - - result = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); - - if (result != NSS_STATUS_SUCCESS) - return false; - - d_printf( "%s:%s:%d:%d:%s:%s:%s\n", - response.data.pw.pw_name, - response.data.pw.pw_passwd, - response.data.pw.pw_uid, - response.data.pw.pw_gid, - response.data.pw.pw_gecos, - response.data.pw.pw_dir, - response.data.pw.pw_shell ); - - return true; -} - -/* pull grent for a given group */ -static bool wbinfo_get_groupinfo(char *group) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.groupname, group); - - result = winbindd_request_response(WINBINDD_GETGRNAM, &request, - &response); - - if ( result != NSS_STATUS_SUCCESS) - return false; - - d_printf( "%s:%s:%d\n", - response.data.gr.gr_name, - response.data.gr.gr_passwd, - response.data.gr.gr_gid ); - - return true; -} - -/* List groups a user is a member of */ - -static bool wbinfo_get_usergroups(char *user) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - int i; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.username, user); - - result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); - - if (result != NSS_STATUS_SUCCESS) - return false; - - for (i = 0; i < response.data.num_entries; i++) - d_printf("%d\n", (int)((gid_t *)response.extra_data.data)[i]); - - SAFE_FREE(response.extra_data.data); - - return true; -} - - -/* List group SIDs a user SID is a member of */ -static bool wbinfo_get_usersids(char *user_sid) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - int i; - const char *s; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - fstrcpy(request.data.sid, user_sid); - - result = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response); - - if (result != NSS_STATUS_SUCCESS) - return false; - - s = (const char *)response.extra_data.data; - for (i = 0; i < response.data.num_entries; i++) { - d_printf("%s\n", s); - s += strlen(s) + 1; - } - - SAFE_FREE(response.extra_data.data); - - return true; -} - -static bool wbinfo_get_userdomgroups(const char *user_sid) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - fstrcpy(request.data.sid, user_sid); - - result = winbindd_request_response(WINBINDD_GETUSERDOMGROUPS, &request, - &response); - - if (result != NSS_STATUS_SUCCESS) - return false; - - if (response.data.num_entries != 0) - printf("%s", (char *)response.extra_data.data); - - SAFE_FREE(response.extra_data.data); - - return true; -} - -/* Convert NetBIOS name to IP */ - -static bool wbinfo_wins_byname(char *name) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.winsreq, name); - - if (winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response) != - NSS_STATUS_SUCCESS) { - return false; - } - - /* Display response */ - - d_printf("%s\n", response.data.winsresp); - - return true; -} - -/* Convert IP to NetBIOS name */ - -static bool wbinfo_wins_byip(char *ip) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.winsreq, ip); - - if (winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response) != - NSS_STATUS_SUCCESS) { - return false; - } - - /* Display response */ - - d_printf("%s\n", response.data.winsresp); - - return true; -} - -/* List trusted domains */ - -static bool wbinfo_list_domains(bool list_all_domains) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.list_all_domains = list_all_domains; - - if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - if (response.extra_data.data) { - const char *extra_data = (char *)response.extra_data.data; - fstring name; - char *p; - - while(next_token(&extra_data, name, "\n", sizeof(fstring))) { - p = strchr(name, '\\'); - if (p == 0) { - d_fprintf(stderr, "Got invalid response: %s\n", - extra_data); - return false; - } - *p = 0; - d_printf("%s\n", name); - } - - SAFE_FREE(response.extra_data.data); - } - - return true; -} - -/* List own domain */ - -static bool wbinfo_list_own_domain(void) -{ - d_printf("%s\n", get_winbind_domain()); - - return true; -} - -/* show sequence numbers */ -static bool wbinfo_show_sequence(const char *domain) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - if ( domain ) - fstrcpy( request.domain_name, domain ); - - /* Send request */ - - if (winbindd_request_response(WINBINDD_SHOW_SEQUENCE, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - if (response.extra_data.data) { - char *extra_data = (char *)response.extra_data.data; - d_printf("%s", extra_data); - SAFE_FREE(response.extra_data.data); - } - - return true; -} - -/* Show domain info */ - -static bool wbinfo_domain_info(const char *domain_name) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if ((strequal(domain_name, ".")) || (domain_name[0] == '\0')) - fstrcpy(request.domain_name, get_winbind_domain()); - else - fstrcpy(request.domain_name, domain_name); - - /* Send request */ - - if (winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("Name : %s\n", response.data.domain_info.name); - d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name); - - d_printf("SID : %s\n", response.data.domain_info.sid); - - d_printf("Active Directory : %s\n", - response.data.domain_info.active_directory ? "Yes" : "No"); - d_printf("Native : %s\n", - response.data.domain_info.native_mode ? "Yes" : "No"); - - d_printf("Primary : %s\n", - response.data.domain_info.primary ? "Yes" : "No"); - - return true; -} - -/* Get a foreign DC's name */ -static bool wbinfo_getdcname(const char *domain_name) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - fstrcpy(request.domain_name, domain_name); - - /* Send request */ - - if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) != - NSS_STATUS_SUCCESS) { - d_fprintf(stderr, "Could not get dc name for %s\n", domain_name); - return false; - } - - /* Display response */ - - d_printf("%s\n", response.data.dc_name); - - return true; -} - -/* Check trust account password */ - -static bool wbinfo_check_secret(void) -{ - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(response); - - result = winbindd_request_response(WINBINDD_CHECK_MACHACC, NULL, &response); - - d_printf("checking the trust secret via RPC calls %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (result != NSS_STATUS_SUCCESS) - d_fprintf(stderr, "error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Convert uid to sid */ - -static bool wbinfo_uid_to_sid(uid_t uid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.uid = uid; - - if (winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("%s\n", response.data.sid.sid); - - return true; -} - -/* Convert gid to sid */ - -static bool wbinfo_gid_to_sid(gid_t gid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.gid = gid; - - if (winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("%s\n", response.data.sid.sid); - - return true; -} - -/* Convert sid to uid */ - -static bool wbinfo_sid_to_uid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("%d\n", (int)response.data.uid); - - return true; -} - -static bool wbinfo_sid_to_gid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("%d\n", (int)response.data.gid); - - return true; -} - -static const char *sid_type_lookup(enum lsa_SidType r) -{ - switch (r) { - case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break; - case SID_NAME_USER: return "SID_NAME_USER"; break; - case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break; - case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break; - case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break; - case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break; - case SID_NAME_DELETED: return "SID_NAME_DELETED"; break; - case SID_NAME_INVALID: return "SID_NAME_INVALID"; break; - case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break; - case SID_NAME_COMPUTER: return "SID_NAME_COMPUTER"; break; - } - return "Invalid sid type\n"; -} - -/* Convert sid to string */ - -static bool wbinfo_lookupsid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send off request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("%s%c%s %s\n", response.data.name.dom_name, - winbind_separator(), response.data.name.name, - sid_type_lookup(response.data.name.type)); - - return true; -} - -/* Convert string to sid */ - -static bool wbinfo_lookupname(char *name) -{ - struct winbindd_request request; - struct winbindd_response response; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - parse_wbinfo_domain_user(name, request.data.name.dom_name, - request.data.name.name); - - if (winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Display response */ - - d_printf("%s %s (%d)\n", response.data.sid.sid, sid_type_lookup(response.data.sid.type), response.data.sid.type); - - return true; -} - -/* Authenticate a user with a plaintext password */ - -static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(request.data.auth.user, username); - fstrcpy(request.data.auth.pass, p + 1); - *p = '%'; - } else - fstrcpy(request.data.auth.user, username); - - request.flags = flags; - - fstrcpy(request.data.auth.krb5_cc_type, cctype); - - request.data.auth.uid = geteuid(); - - result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); - - /* Display response */ - - d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n", - username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype); - - if (response.data.auth.nt_status) - d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status, - response.data.auth.error_string); - - if (result == NSS_STATUS_SUCCESS) { - - if (request.flags & WBFLAG_PAM_INFO3_TEXT) { - if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) { - d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n"); - } - } - - if (response.data.auth.krb5ccname[0] != '\0') { - d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname); - } else { - d_printf("no credentials cached\n"); - } - } - - return result == NSS_STATUS_SUCCESS; -} - -/* Authenticate a user with a plaintext password */ - -static bool wbinfo_auth(char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(request.data.auth.user, username); - fstrcpy(request.data.auth.pass, p + 1); - *p = '%'; - } else - fstrcpy(request.data.auth.user, username); - - result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response); - - /* Display response */ - - d_printf("plaintext password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status, - response.data.auth.error_string); - - return result == NSS_STATUS_SUCCESS; -} - -/* Authenticate a user with a challenge/response */ - -static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - fstring name_user; - fstring name_domain; - fstring pass; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(pass, p + 1); - } - - parse_wbinfo_domain_user(username, name_domain, name_user); - - request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT; - - fstrcpy(request.data.auth_crap.user, name_user); - - fstrcpy(request.data.auth_crap.domain, - name_domain); - - generate_random_buffer(request.data.auth_crap.chal, 8); - - if (lp_client_ntlmv2_auth(lp_ctx)) { - DATA_BLOB server_chal; - DATA_BLOB names_blob; - - DATA_BLOB lm_response; - DATA_BLOB nt_response; - - TALLOC_CTX *mem_ctx; - mem_ctx = talloc_new(NULL); - if (mem_ctx == NULL) { - d_printf("talloc_new failed\n"); - return false; - } - - server_chal = data_blob(request.data.auth_crap.chal, 8); - - /* Pretend this is a login to 'us', for blob purposes */ - names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx)); - - if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal, - &names_blob, - &lm_response, &nt_response, NULL, NULL)) { - data_blob_free(&names_blob); - data_blob_free(&server_chal); - return false; - } - data_blob_free(&names_blob); - data_blob_free(&server_chal); - - memcpy(request.data.auth_crap.nt_resp, nt_response.data, - MIN(nt_response.length, - sizeof(request.data.auth_crap.nt_resp))); - request.data.auth_crap.nt_resp_len = nt_response.length; - - memcpy(request.data.auth_crap.lm_resp, lm_response.data, - MIN(lm_response.length, - sizeof(request.data.auth_crap.lm_resp))); - request.data.auth_crap.lm_resp_len = lm_response.length; - - data_blob_free(&nt_response); - data_blob_free(&lm_response); - - } else { - if (lp_client_lanman_auth(lp_ctx) - && SMBencrypt(pass, request.data.auth_crap.chal, - (unsigned char *)request.data.auth_crap.lm_resp)) { - request.data.auth_crap.lm_resp_len = 24; - } else { - request.data.auth_crap.lm_resp_len = 0; - } - SMBNTencrypt(pass, request.data.auth_crap.chal, - (unsigned char *)request.data.auth_crap.nt_resp); - - request.data.auth_crap.nt_resp_len = 24; - } - - result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response); - - /* Display response */ - - d_printf("challenge/response password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status, - response.data.auth.error_string); - - return result == NSS_STATUS_SUCCESS; -} - -/* Print domain users */ - -static bool print_domain_users(const char *domain) -{ - struct winbindd_request request; - struct winbindd_response response; - const char *extra_data; - fstring name; - - /* Send request to winbind daemon */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (domain) { - /* '.' is the special sign for our own domain */ - if ( strequal(domain, ".") ) - fstrcpy( request.domain_name, get_winbind_domain() ); - else - fstrcpy( request.domain_name, domain ); - } - - if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Look through extra data */ - - if (!response.extra_data.data) - return false; - - extra_data = (const char *)response.extra_data.data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data.data); - - return true; -} - -/* Print domain groups */ - -static bool print_domain_groups(const char *domain) -{ - struct winbindd_request request; - struct winbindd_response response; - const char *extra_data; - fstring name; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - if (domain) { - if ( strequal(domain, ".") ) - fstrcpy( request.domain_name, get_winbind_domain() ); - else - fstrcpy( request.domain_name, domain ); - } - - if (winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response) != - NSS_STATUS_SUCCESS) - return false; - - /* Look through extra data */ - - if (!response.extra_data.data) - return false; - - extra_data = (const char *)response.extra_data.data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data.data); - - return true; -} - -static bool wbinfo_ping(void) -{ - NSS_STATUS result; - - result = winbindd_request_response(WINBINDD_PING, NULL, NULL); - - /* Display response */ - - d_printf("Ping to winbindd %s on fd %d\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd); - - return result == NSS_STATUS_SUCCESS; -} - -/* Main program */ - -enum { - OPT_SET_AUTH_USER = 1000, - OPT_GET_AUTH_USER, - OPT_DOMAIN_NAME, - OPT_SEQUENCE, - OPT_GETDCNAME, - OPT_USERDOMGROUPS, - OPT_USERSIDS, - OPT_ALLOCATE_UID, - OPT_ALLOCATE_GID, - OPT_SEPARATOR, - OPT_LIST_ALL_DOMAINS, - OPT_LIST_OWN_DOMAIN, - OPT_UID_INFO, - OPT_GROUP_INFO, -}; - -int main(int argc, char **argv, char **envp) -{ - int opt; - - poptContext pc; - static char *string_arg; - static char *opt_domain_name; - static int int_arg; - int result = 1; - - struct poptOption long_options[] = { - POPT_AUTOHELP - - /* longName, shortName, argInfo, argPtr, value, descrip, - argDesc */ - - { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"}, - { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" }, - { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" }, - { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" }, - { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, - { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, - { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, - { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, - { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, - { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, - { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" }, - { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" }, - { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" }, - { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" }, - { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" }, - { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" }, - { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" }, - { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" }, - { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" }, - { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, - { "user-domgroups", 0, POPT_ARG_STRING, &string_arg, - OPT_USERDOMGROUPS, "Get user domain groups", "SID" }, - { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" }, - { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, - { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME, - "Get a DC name for a foreign domain", "domainname" }, - { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, - { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" }, -#ifdef HAVE_KRB5 - { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" }, - /* destroys wbinfo --help output */ - /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */ -#endif - { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL }, - POPT_COMMON_VERSION - POPT_COMMON_SAMBA - POPT_TABLEEND - }; - - /* Parse options */ - - pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0); - - /* Parse command line options */ - - if (argc == 1) { - poptPrintHelp(pc, stderr, 0); - return 1; - } - - while((opt = poptGetNextOpt(pc)) != -1) { - /* get the generic configuration parameters like --domain */ - } - - poptFreeContext(pc); - - pc = poptGetContext(NULL, argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - - while((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - case 'u': - if (!print_domain_users(opt_domain_name)) { - d_fprintf(stderr, "Error looking up domain users\n"); - goto done; - } - break; - case 'g': - if (!print_domain_groups(opt_domain_name)) { - d_fprintf(stderr, "Error looking up domain groups\n"); - goto done; - } - break; - case 's': - if (!wbinfo_lookupsid(string_arg)) { - d_fprintf(stderr, "Could not lookup sid %s\n", string_arg); - goto done; - } - break; - case 'n': - if (!wbinfo_lookupname(string_arg)) { - d_fprintf(stderr, "Could not lookup name %s\n", string_arg); - goto done; - } - break; - case 'N': - if (!wbinfo_wins_byname(string_arg)) { - d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg); - goto done; - } - break; - case 'I': - if (!wbinfo_wins_byip(string_arg)) { - d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg); - goto done; - } - break; - case 'U': - if (!wbinfo_uid_to_sid(int_arg)) { - d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg); - goto done; - } - break; - case 'G': - if (!wbinfo_gid_to_sid(int_arg)) { - d_fprintf(stderr, "Could not convert gid %d to sid\n", - int_arg); - goto done; - } - break; - case 'S': - if (!wbinfo_sid_to_uid(string_arg)) { - d_fprintf(stderr, "Could not convert sid %s to uid\n", - string_arg); - goto done; - } - break; - case 'Y': - if (!wbinfo_sid_to_gid(string_arg)) { - d_fprintf(stderr, "Could not convert sid %s to gid\n", - string_arg); - goto done; - } - break; - case 't': - if (!wbinfo_check_secret()) { - d_fprintf(stderr, "Could not check secret\n"); - goto done; - } - break; - case 'm': - if (!wbinfo_list_domains(false)) { - d_fprintf(stderr, "Could not list trusted domains\n"); - goto done; - } - break; - case OPT_SEQUENCE: - if (!wbinfo_show_sequence(opt_domain_name)) { - d_fprintf(stderr, "Could not show sequence numbers\n"); - goto done; - } - break; - case 'D': - if (!wbinfo_domain_info(string_arg)) { - d_fprintf(stderr, "Could not get domain info\n"); - goto done; - } - break; - case 'i': - if (!wbinfo_get_userinfo(string_arg)) { - d_fprintf(stderr, "Could not get info for user %s\n", - string_arg); - goto done; - } - break; - case OPT_UID_INFO: - if ( !wbinfo_get_uidinfo(int_arg)) { - d_fprintf(stderr, "Could not get info for uid " - "%d\n", int_arg); - goto done; - } - break; - case OPT_GROUP_INFO: - if ( !wbinfo_get_groupinfo(string_arg)) { - d_fprintf(stderr, "Could not get info for " - "group %s\n", string_arg); - goto done; - } - break; - case 'r': - if (!wbinfo_get_usergroups(string_arg)) { - d_fprintf(stderr, "Could not get groups for user %s\n", - string_arg); - goto done; - } - break; - case OPT_USERSIDS: - if (!wbinfo_get_usersids(string_arg)) { - d_fprintf(stderr, "Could not get group SIDs for user SID %s\n", - string_arg); - goto done; - } - break; - case OPT_USERDOMGROUPS: - if (!wbinfo_get_userdomgroups(string_arg)) { - d_fprintf(stderr, "Could not get user's domain groups " - "for user SID %s\n", string_arg); - goto done; - } - break; - case 'a': { - bool got_error = false; - - if (!wbinfo_auth(string_arg)) { - d_fprintf(stderr, "Could not authenticate user %s with " - "plaintext password\n", string_arg); - got_error = true; - } - - if (!wbinfo_auth_crap(cmdline_lp_ctx, string_arg)) { - d_fprintf(stderr, "Could not authenticate user %s with " - "challenge/response\n", string_arg); - got_error = true; - } - - if (got_error) - goto done; - break; - } - case 'K': { - uint32_t flags = WBFLAG_PAM_KRB5 | - WBFLAG_PAM_CACHED_LOGIN | - WBFLAG_PAM_FALLBACK_AFTER_KRB5 | - WBFLAG_PAM_INFO3_TEXT; - - if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) { - d_fprintf(stderr, "Could not authenticate user [%s] with " - "Kerberos (ccache: %s)\n", string_arg, "FILE"); - goto done; - } - break; - } - case 'p': - if (!wbinfo_ping()) { - d_fprintf(stderr, "could not ping winbindd!\n"); - goto done; - } - break; - case OPT_GETDCNAME: - if (!wbinfo_getdcname(string_arg)) { - goto done; - } - break; - case OPT_SEPARATOR: { - const char sep = winbind_separator_int(true); - if ( !sep ) { - goto done; - } - d_printf("%c\n", sep); - break; - } - case OPT_LIST_ALL_DOMAINS: - if (!wbinfo_list_domains(true)) { - goto done; - } - break; - case OPT_LIST_OWN_DOMAIN: - if (!wbinfo_list_own_domain()) { - goto done; - } - break; - /* generic configuration options */ - case OPT_DOMAIN_NAME: - break; - default: - d_fprintf(stderr, "Invalid option\n"); - poptPrintHelp(pc, stderr, 0); - goto done; - } - } - - result = 0; - - /* Exit code */ - - done: - poptFreeContext(pc); - return result; -} diff --git a/source4/nsswitch/winbind_client.h b/source4/nsswitch/winbind_client.h deleted file mode 100644 index 2a3956e1fd..0000000000 --- a/source4/nsswitch/winbind_client.h +++ /dev/null @@ -1,25 +0,0 @@ -#include "winbind_nss_config.h" -#include "winbind_struct_protocol.h" - -void winbindd_init_request(struct winbindd_request *req,int rq_type); -void winbindd_free_response(struct winbindd_response *response); -NSS_STATUS winbindd_send_request(int req_type, int need_priv, - struct winbindd_request *request); -NSS_STATUS winbindd_get_response(struct winbindd_response *response); -NSS_STATUS winbindd_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); -NSS_STATUS winbindd_priv_request_response(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); -int winbindd_read_reply(struct winbindd_response *response); - -bool winbind_env_set(void); -bool winbind_off(void); -bool winbind_on(void); - -int winbind_write_sock(void *buffer, int count, int recursing, int need_priv); -int winbind_read_sock(void *buffer, int count); -void winbind_close_sock(void); - -const char *nss_err_str(NSS_STATUS ret); diff --git a/source4/nsswitch/winbind_nss.h b/source4/nsswitch/winbind_nss.h deleted file mode 100644 index 0a3bc7cefa..0000000000 --- a/source4/nsswitch/winbind_nss.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - A common place to work out how to define NSS_STATUS on various - platforms. - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _NSSWITCH_NSS_H -#define _NSSWITCH_NSS_H - -#ifdef HAVE_NSS_COMMON_H - -/* - * Sun Solaris - */ - -#include "nsswitch/winbind_nss_solaris.h" - -#elif HAVE_NSS_H - -/* - * Linux (glibc) - */ - -#include "nsswitch/winbind_nss_linux.h" - -#elif HAVE_NS_API_H - -/* - * SGI IRIX - */ - -#include "nsswitch/winbind_nss_irix.h" - -#elif defined(HPUX) && defined(HAVE_NSSWITCH_H) - -/* HP-UX 11 */ - -#include "nsswitch/winbind_nss_hpux.h" - -#elif defined(__NetBSD__) && defined(HAVE_GETPWENT_R) - -/* - * NetBSD 3 and newer - */ - -#include "nsswitch/winbind_nss_netbsd.h" - -#else /* Nothing's defined. Neither gnu nor netbsd nor sun nor hp */ - -typedef enum -{ - NSS_STATUS_SUCCESS=0, - NSS_STATUS_NOTFOUND=1, - NSS_STATUS_UNAVAIL=2, - NSS_STATUS_TRYAGAIN=3 -} NSS_STATUS; - -#endif - -#endif /* _NSSWITCH_NSS_H */ diff --git a/source4/nsswitch/winbind_nss_config.h b/source4/nsswitch/winbind_nss_config.h deleted file mode 100644 index c5bc853770..0000000000 --- a/source4/nsswitch/winbind_nss_config.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_CONFIG_H -#define _WINBIND_NSS_CONFIG_H - -/* shutup the compiler warnings due to krb5.h on 64-bit sles9 */ -#ifdef SIZEOF_LONG -#undef SIZEOF_LONG -#endif - - -/* Include header files from data in config.h file */ - -#ifndef NO_CONFIG_H -#include "../replace/replace.h" -#endif - -#include "system/passwd.h" -#include "system/filesys.h" -#include "system/network.h" - -#include "nsswitch/winbind_nss.h" - -/* Some systems (SCO) treat UNIX domain sockets as FIFOs */ - -#ifndef S_IFSOCK -#define S_IFSOCK S_IFIFO -#endif - -#ifndef S_ISSOCK -#define S_ISSOCK(mode) ((mode & S_IFSOCK) == S_IFSOCK) -#endif - -#endif diff --git a/source4/nsswitch/winbind_nss_hpux.h b/source4/nsswitch/winbind_nss_hpux.h deleted file mode 100644 index 62cf3c26c5..0000000000 --- a/source4/nsswitch/winbind_nss_hpux.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Donated by HP to enable Winbindd to build on HPUX 11.x. - Copyright (C) Jeremy Allison 2002. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#ifndef _WINBIND_NSS_HPUX_H -#define _WINBIND_NSS_HPUX_H - -#include - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -#ifdef HAVE_SYNCH_H -#include -#endif -#ifdef HAVE_PTHREAD_H -#include -#endif - -typedef enum { - NSS_SUCCESS, - NSS_NOTFOUND, - NSS_UNAVAIL, - NSS_TRYAGAIN -} nss_status_t; - -typedef nss_status_t NSS_STATUS; - -struct nss_backend; - -typedef nss_status_t (*nss_backend_op_t)(struct nss_backend *, void *args); - -struct nss_backend { - nss_backend_op_t *ops; - int n_ops; -}; -typedef struct nss_backend nss_backend_t; -typedef int nss_dbop_t; - -#include -#include -#include - -#ifndef NSS_INCLUDE_UNSAFE -#define NSS_INCLUDE_UNSAFE 1 /* Build old, MT-unsafe interfaces, */ -#endif /* NSS_INCLUDE_UNSAFE */ - -enum nss_netgr_argn { - NSS_NETGR_MACHINE, - NSS_NETGR_USER, - NSS_NETGR_DOMAIN, - NSS_NETGR_N -}; - -enum nss_netgr_status { - NSS_NETGR_FOUND, - NSS_NETGR_NO, - NSS_NETGR_NOMEM -}; - -typedef unsigned nss_innetgr_argc; -typedef char **nss_innetgr_argv; - -struct nss_innetgr_1arg { - nss_innetgr_argc argc; - nss_innetgr_argv argv; -}; - -typedef struct { - void *result; /* "result" parameter to getXbyY_r() */ - char *buffer; /* "buffer" " " */ - int buflen; /* "buflen" " " */ -} nss_XbyY_buf_t; - -extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size); -extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *); - -union nss_XbyY_key { - uid_t uid; - gid_t gid; - const char *name; - int number; - struct { - long net; - int type; - } netaddr; - struct { - const char *addr; - int len; - int type; - } hostaddr; - struct { - union { - const char *name; - int port; - } serv; - const char *proto; - } serv; - void *ether; -}; - -typedef struct nss_XbyY_args { - nss_XbyY_buf_t buf; - int stayopen; - /* - * Support for setXXXent(stayopen) - * Used only in hosts, protocols, - * networks, rpc, and services. - */ - int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen); - union nss_XbyY_key key; - - void *returnval; - int erange; - int h_errno; - nss_status_t status; -} nss_XbyY_args_t; - -#endif /* _WINBIND_NSS_HPUX_H */ diff --git a/source4/nsswitch/winbind_nss_irix.h b/source4/nsswitch/winbind_nss_irix.h deleted file mode 100644 index b40b14b0b0..0000000000 --- a/source4/nsswitch/winbind_nss_irix.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_IRIX_H -#define _WINBIND_NSS_IRIX_H - -/* following required to prevent warnings of double definition - * of datum from ns_api.h -*/ -#ifdef DATUM -#define _DATUM_DEFINED -#endif - -#include - -typedef enum -{ - NSS_STATUS_SUCCESS=NS_SUCCESS, - NSS_STATUS_NOTFOUND=NS_NOTFOUND, - NSS_STATUS_UNAVAIL=NS_UNAVAIL, - NSS_STATUS_TRYAGAIN=NS_TRYAGAIN -} NSS_STATUS; - -#endif /* _WINBIND_NSS_IRIX_H */ diff --git a/source4/nsswitch/winbind_nss_linux.c b/source4/nsswitch/winbind_nss_linux.c deleted file mode 100644 index ac53979ced..0000000000 --- a/source4/nsswitch/winbind_nss_linux.c +++ /dev/null @@ -1,1281 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Windows NT Domain nsswitch module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "winbind_client.h" - -/* Maximum number of users to pass back over the unix domain socket - per call. This is not a static limit on the total number of users - or groups returned in total. */ - -#define MAX_GETPWENT_USERS 250 -#define MAX_GETGRENT_USERS 250 - -NSS_STATUS _nss_winbind_setpwent(void); -NSS_STATUS _nss_winbind_endpwent(void); -NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_setgrent(void); -NSS_STATUS _nss_winbind_endgrent(void); -NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, - long int limit, int *errnop); -NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, - int *num_groups, char *buffer, size_t buf_size, - int *errnop); -NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); -NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); -NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, - size_t buflen, int *errnop); - -/* Prototypes from wb_common.c */ - -extern int winbindd_fd; - -/* Allocate some space from the nss static buffer. The buffer and buflen - are the pointers passed in by the C library to the _nss_ntdom_* - functions. */ - -static char *get_static(char **buffer, size_t *buflen, size_t len) -{ - char *result; - - /* Error check. We return false if things aren't set up right, or - there isn't enough buffer space left. */ - - if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { - return NULL; - } - - /* Return an index into the static buffer */ - - result = *buffer; - *buffer += len; - *buflen -= len; - - return result; -} - -/* I've copied the strtok() replacement function next_token() from - lib/util_str.c as I really don't want to have to link in any other - objects if I can possibly avoid it. */ - -static bool next_token(char **ptr,char *buff,const char *sep, size_t bufsize) -{ - char *s; - bool quoted; - size_t len=1; - - if (!ptr) return false; - - s = *ptr; - - /* default to simple separators */ - if (!sep) sep = " \t\n\r"; - - /* find the first non sep char */ - while (*s && strchr(sep,*s)) s++; - - /* nothing left? */ - if (! *s) return false; - - /* copy over the token */ - for (quoted = false; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { - if (*s == '\"') { - quoted = !quoted; - } else { - len++; - *buff++ = *s; - } - } - - *ptr = (*s) ? s+1 : s; - *buff = 0; - - return true; -} - - -/* Fill a pwent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_pwent(struct passwd *result, - struct winbindd_pw *pw, - char **buffer, size_t *buflen) -{ - /* User name */ - - if ((result->pw_name = - get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_name, pw->pw_name); - - /* Password */ - - if ((result->pw_passwd = - get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_passwd, pw->pw_passwd); - - /* [ug]id */ - - result->pw_uid = pw->pw_uid; - result->pw_gid = pw->pw_gid; - - /* GECOS */ - - if ((result->pw_gecos = - get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_gecos, pw->pw_gecos); - - /* Home directory */ - - if ((result->pw_dir = - get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_dir, pw->pw_dir); - - /* Logon shell */ - - if ((result->pw_shell = - get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_shell, pw->pw_shell); - - /* The struct passwd for Solaris has some extra fields which must - be initialised or nscd crashes. */ - -#if HAVE_PASSWD_PW_COMMENT - result->pw_comment = ""; -#endif - -#if HAVE_PASSWD_PW_AGE - result->pw_age = ""; -#endif - - return NSS_STATUS_SUCCESS; -} - -/* Fill a grent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, - char *gr_mem, char **buffer, size_t *buflen) -{ - fstring name; - int i; - char *tst; - - /* Group name */ - - if ((result->gr_name = - get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_name, gr->gr_name); - - /* Password */ - - if ((result->gr_passwd = - get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_passwd, gr->gr_passwd); - - /* gid */ - - result->gr_gid = gr->gr_gid; - - /* Group membership */ - - if ((gr->num_gr_mem < 0) || !gr_mem) { - gr->num_gr_mem = 0; - } - - /* this next value is a pointer to a pointer so let's align it */ - - /* Calculate number of extra bytes needed to align on pointer size boundry */ - if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0) - i = sizeof(char*) - i; - - if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * - sizeof(char *)+i))) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - result->gr_mem = (char **)(tst + i); - - if (gr->num_gr_mem == 0) { - - /* Group is empty */ - - *(result->gr_mem) = NULL; - return NSS_STATUS_SUCCESS; - } - - /* Start looking at extra data */ - - i = 0; - - while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) { - - /* Allocate space for member */ - - if (((result->gr_mem)[i] = - get_static(buffer, buflen, strlen(name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy((result->gr_mem)[i], name); - i++; - } - - /* Terminate list */ - - (result->gr_mem)[i] = NULL; - - return NSS_STATUS_SUCCESS; -} - -/* - * NSS user functions - */ - -static struct winbindd_response getpwent_response; - -static int ndx_pw_cache; /* Current index into pwd cache */ -static int num_pw_cache; /* Current size of pwd cache */ - -/* Rewind "file pointer" to start of ntdom password database */ - -NSS_STATUS -_nss_winbind_setpwent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setpwent\n", getpid()); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - winbindd_free_response(&getpwent_response); - } - - ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - return ret; -} - -/* Close ntdom password database "file pointer" */ - -NSS_STATUS -_nss_winbind_endpwent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endpwent\n", getpid()); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - winbindd_free_response(&getpwent_response); - } - - ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - return ret; -} - -/* Fetch the next password entry from ntdom password database */ - -NSS_STATUS -_nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - static int called_again; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwent\n", getpid()); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_pw_cache < num_pw_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_pw_cache > 0) { - winbindd_free_response(&getpwent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getpwent_response); - - request.data.num_entries = MAX_GETPWENT_USERS; - - ret = winbindd_request_response(WINBINDD_GETPWENT, &request, - &getpwent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_pw *pw_cache; - - /* Fill cache */ - - ndx_pw_cache = 0; - num_pw_cache = getpwent_response.data.num_entries; - - /* Return a result */ - - return_result: - - pw_cache = (struct winbindd_pw *) - getpwent_response.extra_data.data; - - /* Check data is valid */ - - if (pw_cache == NULL) { - ret = NSS_STATUS_NOTFOUND; - goto done; - } - - ret = fill_pwent(result, &pw_cache[ndx_pw_cache], - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = true; - *errnop = errno = ERANGE; - goto done; - } - - *errnop = errno = 0; - called_again = false; - ndx_pw_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_pw_cache == num_pw_cache) { - ndx_pw_cache = num_pw_cache = 0; - winbindd_free_response(&getpwent_response); - } - } - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - return ret; -} - -/* Return passwd struct from uid */ - -NSS_STATUS -_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response=0; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid); -#endif - - /* If our static buffer needs to be expanded we are called again */ - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = errno = 0; - } - - winbindd_free_response(&response); - done: - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(), - (unsigned int)uid, nss_err_str(ret), ret); -#endif - return ret; -} - -/* Return passwd struct from username */ -NSS_STATUS -_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.username, name, - sizeof(request.data.username) - 1); - request.data.username - [sizeof(request.data.username) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = errno = 0; - } - - winbindd_free_response(&response); - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(), - name, nss_err_str(ret), ret); -#endif - return ret; -} - -/* - * NSS group functions - */ - -static struct winbindd_response getgrent_response; - -static int ndx_gr_cache; /* Current index into grp cache */ -static int num_gr_cache; /* Current size of grp cache */ - -/* Rewind "file pointer" to start of ntdom group database */ - -NSS_STATUS -_nss_winbind_setgrent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setgrent\n", getpid()); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - winbindd_free_response(&getgrent_response); - } - - ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - return ret; -} - -/* Close "file pointer" for ntdom group database */ - -NSS_STATUS -_nss_winbind_endgrent(void) -{ - NSS_STATUS ret; -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endgrent\n", getpid()); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - winbindd_free_response(&getgrent_response); - } - - ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL); -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - return ret; -} - -/* Get next entry from ntdom group database */ - -static NSS_STATUS -winbind_getgrent(enum winbindd_cmd cmd, - struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_request request; - static int called_again; - - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrent\n", getpid()); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_gr_cache < num_gr_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_gr_cache > 0) { - winbindd_free_response(&getgrent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getgrent_response); - - request.data.num_entries = MAX_GETGRENT_USERS; - - ret = winbindd_request_response(cmd, &request, - &getgrent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_gr *gr_cache; - int mem_ofs; - - /* Fill cache */ - - ndx_gr_cache = 0; - num_gr_cache = getgrent_response.data.num_entries; - - /* Return a result */ - - return_result: - - gr_cache = (struct winbindd_gr *) - getgrent_response.extra_data.data; - - /* Check data is valid */ - - if (gr_cache == NULL) { - ret = NSS_STATUS_NOTFOUND; - goto done; - } - - /* Fill group membership. The offset into the extra data - for the group membership is the reported offset plus the - size of all the winbindd_gr records returned. */ - - mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + - num_gr_cache * sizeof(struct winbindd_gr); - - ret = fill_grent(result, &gr_cache[ndx_gr_cache], - ((char *)getgrent_response.extra_data.data)+mem_ofs, - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = true; - *errnop = errno = ERANGE; - goto done; - } - - *errnop = 0; - called_again = false; - ndx_gr_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_gr_cache == num_gr_cache) { - ndx_gr_cache = num_gr_cache = 0; - winbindd_free_response(&getgrent_response); - } - } - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(), - nss_err_str(ret), ret); -#endif - return ret; -} - - -NSS_STATUS -_nss_winbind_getgrent_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); -} - -NSS_STATUS -_nss_winbind_getgrlst_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); -} - -/* Return group struct from group name */ - -NSS_STATUS -_nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.groupname, name, - sizeof(request.data.groupname)); - request.data.groupname - [sizeof(request.data.groupname) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = 0; - } - - winbindd_free_response(&response); - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(), - name, nss_err_str(ret), ret); -#endif - return ret; -} - -/* Return group struct from gid */ - -NSS_STATUS -_nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.gid = gid; - - ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - (char *)response.extra_data.data, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = true; - *errnop = errno = ERANGE; - goto done; - } - - keep_response = false; - *errnop = 0; - } - - winbindd_free_response(&response); - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(), - (unsigned int)gid, nss_err_str(ret), ret); -#endif - return ret; -} - -/* Initialise supplementary groups */ - -NSS_STATUS -_nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, long int limit, - int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - int i; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), - user, group); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.username, user, - sizeof(request.data.username) - 1); - - ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - int num_gids = response.data.num_entries; - gid_t *gid_list = (gid_t *)response.extra_data.data; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS " - "and %d gids\n", getpid(), - user, num_gids); -#endif - if (gid_list == NULL) { - ret = NSS_STATUS_NOTFOUND; - goto done; - } - - /* Copy group list to client */ - - for (i = 0; i < num_gids; i++) { - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s (%d): " - "processing gid %d \n", getpid(), - user, group, gid_list[i]); -#endif - - /* Skip primary group */ - - if (gid_list[i] == group) { - continue; - } - - /* Filled buffer ? If so, resize. */ - - if (*start == *size) { - long int newsize; - gid_t *newgroups; - - newsize = 2 * (*size); - if (limit > 0) { - if (*size == limit) { - goto done; - } - if (newsize > limit) { - newsize = limit; - } - } - - newgroups = (gid_t *) - realloc((*groups), - newsize * sizeof(**groups)); - if (!newgroups) { - *errnop = ENOMEM; - ret = NSS_STATUS_NOTFOUND; - goto done; - } - *groups = newgroups; - *size = newsize; - } - - /* Add to buffer */ - - (*groups)[*start] = gid_list[i]; - *start += 1; - } - } - - /* Back to your regularly scheduled programming */ - - done: -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(), - user, nss_err_str(ret), ret); -#endif - return ret; -} - - -/* return a list of group SIDs for a user SID */ -NSS_STATUS -_nss_winbind_getusersids(const char *user_sid, char **group_sids, - int *num_groups, - char *buffer, size_t buf_size, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response); - - if (ret != NSS_STATUS_SUCCESS) { - goto done; - } - - if (buf_size < response.length - sizeof(response)) { - ret = NSS_STATUS_TRYAGAIN; - errno = *errnop = ERANGE; - goto done; - } - - *num_groups = response.data.num_entries; - *group_sids = buffer; - memcpy(buffer, response.extra_data.data, response.length - sizeof(response)); - errno = *errnop = 0; - - done: - winbindd_free_response(&response); - return ret; -} - - -/* map a user or group name to a SID string */ -NSS_STATUS -_nss_winbind_nametosid(const char *name, char **sid, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.name.name, name, - sizeof(request.data.name.name) - 1); - request.data.name.name[sizeof(request.data.name.name) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - if (buflen < strlen(response.data.sid.sid)+1) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - *errnop = errno = 0; - *sid = buffer; - strcpy(*sid, response.data.sid.sid); - -failed: - winbindd_free_response(&response); - return ret; -} - -/* map a sid string to a user or group name */ -NSS_STATUS -_nss_winbind_sidtoname(const char *sid, char **name, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - static char sep_char; - unsigned needed; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - /* we need to fetch the separator first time through */ - if (!sep_char) { - ret = winbindd_request_response(WINBINDD_INFO, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - sep_char = response.data.info.winbind_separator; - winbindd_free_response(&response); - } - - - strncpy(request.data.sid, sid, - sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - needed = - strlen(response.data.name.dom_name) + - strlen(response.data.name.name) + 2; - - if (buflen < needed) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - snprintf(buffer, needed, "%s%c%s", - response.data.name.dom_name, - sep_char, - response.data.name.name); - - *name = buffer; - *errnop = errno = 0; - -failed: - winbindd_free_response(&response); - return ret; -} - -/* map a sid to a uid */ -NSS_STATUS -_nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - *uid = response.data.uid; - -failed: - return ret; -} - -/* map a sid to a gid */ -NSS_STATUS -_nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); - request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - - ret = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - *gid = response.data.gid; - -failed: - return ret; -} - -/* map a uid to a SID string */ -NSS_STATUS -_nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - if (buflen < strlen(response.data.sid.sid)+1) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - *errnop = errno = 0; - *sid = buffer; - strcpy(*sid, response.data.sid.sid); - -failed: - winbindd_free_response(&response); - return ret; -} - -/* map a gid to a SID string */ -NSS_STATUS -_nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_response response; - struct winbindd_request request; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid); -#endif - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.gid = gid; - - ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response); - if (ret != NSS_STATUS_SUCCESS) { - *errnop = errno = EINVAL; - goto failed; - } - - if (buflen < strlen(response.data.sid.sid)+1) { - ret = NSS_STATUS_TRYAGAIN; - *errnop = errno = ERANGE; - goto failed; - } - - *errnop = errno = 0; - *sid = buffer; - strcpy(*sid, response.data.sid.sid); - -failed: - winbindd_free_response(&response); - return ret; -} diff --git a/source4/nsswitch/winbind_nss_linux.h b/source4/nsswitch/winbind_nss_linux.h deleted file mode 100644 index 74aaec5ce6..0000000000 --- a/source4/nsswitch/winbind_nss_linux.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_LINUX_H -#define _WINBIND_NSS_LINUX_H - -#include - -typedef enum nss_status NSS_STATUS; - -#endif /* _WINBIND_NSS_LINUX_H */ diff --git a/source4/nsswitch/winbind_nss_netbsd.h b/source4/nsswitch/winbind_nss_netbsd.h deleted file mode 100644 index dceb57c784..0000000000 --- a/source4/nsswitch/winbind_nss_netbsd.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - NetBSD loadable authentication module, providing identification - routines against Samba winbind/Windows NT Domain - - Copyright (C) Luke Mewburn 2004-2005 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_NETBSD_H -#define _WINBIND_NSS_NETBSD_H - -#include - - /* dynamic nsswitch with "new" getpw* nsdispatch API available */ -#if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R) - -typedef int NSS_STATUS; - -#define NSS_STATUS_SUCCESS NS_SUCCESS -#define NSS_STATUS_NOTFOUND NS_NOTFOUND -#define NSS_STATUS_UNAVAIL NS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NS_TRYAGAIN - -#endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */ - -#endif /* _WINBIND_NSS_NETBSD_H */ diff --git a/source4/nsswitch/winbind_nss_solaris.h b/source4/nsswitch/winbind_nss_solaris.h deleted file mode 100644 index 941b3e66df..0000000000 --- a/source4/nsswitch/winbind_nss_solaris.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef _WINBIND_NSS_SOLARIS_H -#define _WINBIND_NSS_SOLARIS_H - -/* Solaris has a broken nss_common header file containing C++ reserved names. */ -#ifndef __cplusplus -#undef class -#undef private -#undef public -#undef protected -#undef template -#undef this -#undef new -#undef delete -#undef friend -#endif - -#include - -/* -TODO: we need to cleanup samba4's headers.. - -#ifndef __cplusplus -#define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define this #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define new #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define delete #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define friend #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#endif -*/ - -#include -#include - -typedef nss_status_t NSS_STATUS; - -#define NSS_STATUS_SUCCESS NSS_SUCCESS -#define NSS_STATUS_NOTFOUND NSS_NOTFOUND -#define NSS_STATUS_UNAVAIL NSS_UNAVAIL -#define NSS_STATUS_TRYAGAIN NSS_TRYAGAIN - -/* The solaris winbind is implemented as a wrapper around the linux - version. */ - -NSS_STATUS _nss_winbind_setpwent(void); -NSS_STATUS _nss_winbind_endpwent(void); -NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result, - char* buffer, size_t buflen, int* errnop); - -NSS_STATUS _nss_winbind_setgrent(void); -NSS_STATUS _nss_winbind_endgrent(void); -NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer, - size_t buflen, int* errnop); -NSS_STATUS _nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop); -NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop); - -#endif /* _WINBIND_NSS_SOLARIS_H */ diff --git a/source4/nsswitch/winbind_struct_protocol.h b/source4/nsswitch/winbind_struct_protocol.h deleted file mode 100644 index 8003ea9585..0000000000 --- a/source4/nsswitch/winbind_struct_protocol.h +++ /dev/null @@ -1,507 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - Copyright (C) Gerald Carter 2006 - - You are free to use this interface definition in any way you see - fit, including without restriction, using this header in your own - products. You do not need to give any attribution. -*/ - -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0) -#endif - -#ifndef _WINBINDD_NTDOM_H -#define _WINBINDD_NTDOM_H - -#define _PSTRING -#define FSTRING_LEN 256 - -typedef char fstring[FSTRING_LEN]; - -#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1) -#define fstrcat(d,s) safe_strcat((d),(s),sizeof(fstring)-1) - -#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */ - -/* Let the build environment override the public winbindd socket location. This - * is needed for launchd support -- jpeach. - */ -#ifndef WINBINDD_SOCKET_DIR -#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */ -#endif - -/* - * when compiled with socket_wrapper support - * the location of the WINBINDD_SOCKET_DIR - * can be overwritten via an environment variable - */ -#define WINBINDD_SOCKET_DIR_ENVVAR "WINBINDD_SOCKET_DIR" - -#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */ -#define WINBINDD_DONT_ENV "_NO_WINBINDD" -#define WINBINDD_LOCATOR_KDC_ADDRESS "WINBINDD_LOCATOR_KDC_ADDRESS" - -/* Update this when you change the interface. */ - -#define WINBIND_INTERFACE_VERSION 19 - -/* Have to deal with time_t being 4 or 8 bytes due to structure alignment. - On a 64bit Linux box, we have to support a constant structure size - between /lib/libnss_winbind.so.2 and /li64/libnss_winbind.so.2. - The easiest way to do this is to always use 8byte values for time_t. */ - -#define SMB_TIME_T int64_t - -/* Socket commands */ - -enum winbindd_cmd { - - WINBINDD_INTERFACE_VERSION, /* Always a well known value */ - - /* Get users and groups */ - - WINBINDD_GETPWNAM, - WINBINDD_GETPWUID, - WINBINDD_GETGRNAM, - WINBINDD_GETGRGID, - WINBINDD_GETGROUPS, - - /* Enumerate users and groups */ - - WINBINDD_SETPWENT, - WINBINDD_ENDPWENT, - WINBINDD_GETPWENT, - WINBINDD_SETGRENT, - WINBINDD_ENDGRENT, - WINBINDD_GETGRENT, - - /* PAM authenticate and password change */ - - WINBINDD_PAM_AUTH, - WINBINDD_PAM_AUTH_CRAP, - WINBINDD_PAM_CHAUTHTOK, - WINBINDD_PAM_LOGOFF, - WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, - - /* List various things */ - - WINBINDD_LIST_USERS, /* List w/o rid->id mapping */ - WINBINDD_LIST_GROUPS, /* Ditto */ - WINBINDD_LIST_TRUSTDOM, - - /* SID conversion */ - - WINBINDD_LOOKUPSID, - WINBINDD_LOOKUPNAME, - WINBINDD_LOOKUPRIDS, - - /* Lookup functions */ - - WINBINDD_SID_TO_UID, - WINBINDD_SID_TO_GID, - WINBINDD_SIDS_TO_XIDS, - WINBINDD_UID_TO_SID, - WINBINDD_GID_TO_SID, - - WINBINDD_ALLOCATE_UID, - WINBINDD_ALLOCATE_GID, - WINBINDD_SET_MAPPING, - WINBINDD_SET_HWM, - - /* Miscellaneous other stuff */ - - WINBINDD_DUMP_MAPS, - - WINBINDD_CHECK_MACHACC, /* Check machine account pw works */ - WINBINDD_PING, /* Just tell me winbind is running */ - WINBINDD_INFO, /* Various bit of info. Currently just tidbits */ - WINBINDD_DOMAIN_NAME, /* The domain this winbind server is a member of (lp_workgroup()) */ - - WINBINDD_DOMAIN_INFO, /* Most of what we know from - struct winbindd_domain */ - WINBINDD_GETDCNAME, /* Issue a GetDCName Request */ - WINBINDD_DSGETDCNAME, /* Issue a DsGetDCName Request */ - - WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */ - - /* WINS commands */ - - WINBINDD_WINS_BYIP, - WINBINDD_WINS_BYNAME, - - /* this is like GETGRENT but gives an empty group list */ - WINBINDD_GETGRLST, - - WINBINDD_NETBIOS_NAME, /* The netbios name of the server */ - - /* find the location of our privileged pipe */ - WINBINDD_PRIV_PIPE_DIR, - - /* return a list of group sids for a user sid */ - WINBINDD_GETUSERSIDS, - - /* Various group queries */ - WINBINDD_GETUSERDOMGROUPS, - - /* Initialize connection in a child */ - WINBINDD_INIT_CONNECTION, - - /* Blocking calls that are not allowed on the main winbind pipe, only - * between parent and children */ - WINBINDD_DUAL_SID2UID, - WINBINDD_DUAL_SID2GID, - WINBINDD_DUAL_SIDS2XIDS, - WINBINDD_DUAL_UID2SID, - WINBINDD_DUAL_GID2SID, - WINBINDD_DUAL_SET_MAPPING, - WINBINDD_DUAL_SET_HWM, - WINBINDD_DUAL_DUMP_MAPS, - - /* Wrapper around possibly blocking unix nss calls */ - WINBINDD_DUAL_UID2NAME, - WINBINDD_DUAL_NAME2UID, - WINBINDD_DUAL_GID2NAME, - WINBINDD_DUAL_NAME2GID, - - WINBINDD_DUAL_USERINFO, - WINBINDD_DUAL_GETSIDALIASES, - - /* Complete the challenge phase of the NTLM authentication - protocol using cached password. */ - WINBINDD_CCACHE_NTLMAUTH, - - WINBINDD_NUM_CMDS -}; - -typedef struct winbindd_pw { - fstring pw_name; - fstring pw_passwd; - uid_t pw_uid; - gid_t pw_gid; - fstring pw_gecos; - fstring pw_dir; - fstring pw_shell; -} WINBINDD_PW; - - -typedef struct winbindd_gr { - fstring gr_name; - fstring gr_passwd; - gid_t gr_gid; - uint32_t num_gr_mem; - uint32_t gr_mem_ofs; /* offset to group membership */ -} WINBINDD_GR; - -/* PAM specific request flags */ -#define WBFLAG_PAM_INFO3_NDR 0x00000001 -#define WBFLAG_PAM_INFO3_TEXT 0x00000002 -#define WBFLAG_PAM_USER_SESSION_KEY 0x00000004 -#define WBFLAG_PAM_LMKEY 0x00000008 -#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x00000010 -#define WBFLAG_PAM_UNIX_NAME 0x00000080 -#define WBFLAG_PAM_AFS_TOKEN 0x00000100 -#define WBFLAG_PAM_NT_STATUS_SQUASH 0x00000200 -#define WBFLAG_PAM_KRB5 0x00001000 -#define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x00002000 -#define WBFLAG_PAM_CACHED_LOGIN 0x00004000 -#define WBFLAG_PAM_GET_PWD_POLICY 0x00008000 /* not used */ - -/* generic request flags */ -#define WBFLAG_QUERY_ONLY 0x00000020 /* not used */ -/* This is a flag that can only be sent from parent to child */ -#define WBFLAG_IS_PRIVILEGED 0x00000400 /* not used */ -/* Flag to say this is a winbindd internal send - don't recurse. */ -#define WBFLAG_RECURSE 0x00000800 - - -#define WINBINDD_MAX_EXTRA_DATA (128*1024) - -/* Winbind request structure */ - -/******************************************************************************* - * This structure MUST be the same size in the 32bit and 64bit builds - * for compatibility between /lib64/libnss_winbind.so and /lib/libnss_winbind.so - * - * DO NOT CHANGE THIS STRUCTURE WITHOUT TESTING THE 32BIT NSS LIB AGAINST - * A 64BIT WINBINDD --jerry - ******************************************************************************/ - -struct winbindd_request { - uint32_t length; - enum winbindd_cmd cmd; /* Winbindd command to execute */ - enum winbindd_cmd original_cmd; /* Original Winbindd command - issued to parent process */ - pid_t pid; /* pid of calling process */ - uint32_t wb_flags; /* generic flags */ - uint32_t flags; /* flags relevant *only* to a given request */ - fstring domain_name; /* name of domain for which the request applies */ - - union { - fstring winsreq; /* WINS request */ - fstring username; /* getpwnam */ - fstring groupname; /* getgrnam */ - uid_t uid; /* getpwuid, uid_to_sid */ - gid_t gid; /* getgrgid, gid_to_sid */ - struct { - /* We deliberatedly don't split into domain/user to - avoid having the client know what the separator - character is. */ - fstring user; - fstring pass; - char require_membership_of_sid[1024]; - fstring krb5_cc_type; - uid_t uid; - } auth; /* pam_winbind auth module */ - struct { - uint8_t chal[8]; - uint32_t logon_parameters; - fstring user; - fstring domain; - fstring lm_resp; - uint32_t lm_resp_len; - fstring nt_resp; - uint32_t nt_resp_len; - fstring workstation; - fstring require_membership_of_sid; - } auth_crap; - struct { - fstring user; - fstring oldpass; - fstring newpass; - } chauthtok; /* pam_winbind passwd module */ - struct { - fstring user; - fstring domain; - uint8_t new_nt_pswd[516]; - uint16_t new_nt_pswd_len; - uint8_t old_nt_hash_enc[16]; - uint16_t old_nt_hash_enc_len; - uint8_t new_lm_pswd[516]; - uint16_t new_lm_pswd_len; - uint8_t old_lm_hash_enc[16]; - uint16_t old_lm_hash_enc_len; - } chng_pswd_auth_crap;/* pam_winbind passwd module */ - struct { - fstring user; - fstring krb5ccname; - uid_t uid; - } logoff; /* pam_winbind session module */ - fstring sid; /* lookupsid, sid_to_[ug]id */ - struct { - fstring dom_name; /* lookupname */ - fstring name; - } name; - uint32_t num_entries; /* getpwent, getgrent */ - struct { - fstring username; - fstring groupname; - } acct_mgt; - struct { - bool is_primary; - fstring dcname; - } init_conn; - struct { - fstring sid; - fstring name; - } dual_sid2id; - struct { - fstring sid; - uint32_t type; - uint32_t id; - } dual_idmapset; - bool list_all_domains; - - struct { - uid_t uid; - fstring user; - /* the effective uid of the client, must be the uid for 'user'. - This is checked by the main daemon, trusted by children. */ - /* if the blobs are length zero, then this doesn't - produce an actual challenge response. It merely - succeeds if there are cached credentials available - that could be used. */ - uint32_t initial_blob_len; /* blobs in extra_data */ - uint32_t challenge_blob_len; - } ccache_ntlm_auth; - - /* padding -- needed to fix alignment between 32bit and 64bit libs. - The size is the sizeof the union without the padding aligned on - an 8 byte boundary. --jerry */ - - char padding[1800]; - } data; - union { - SMB_TIME_T padding; - char *data; - } extra_data; - uint32_t extra_len; - char null_term; -}; - -/* Response values */ - -enum winbindd_result { - WINBINDD_ERROR, - WINBINDD_PENDING, - WINBINDD_OK -}; - -/* Winbind response structure */ - -/******************************************************************************* - * This structure MUST be the same size in the 32bit and 64bit builds - * for compatibility between /lib64/libnss_winbind.so and /lib/libnss_winbind.so - * - * DO NOT CHANGE THIS STRUCTURE WITHOUT TESTING THE 32BIT NSS LIB AGAINST - * A 64BIT WINBINDD --jerry - ******************************************************************************/ - -struct winbindd_response { - - /* Header information */ - - uint32_t length; /* Length of response */ - enum winbindd_result result; /* Result code */ - - /* Fixed length return data */ - - union { - int interface_version; /* Try to ensure this is always in the same spot... */ - - fstring winsresp; /* WINS response */ - - /* getpwnam, getpwuid */ - - struct winbindd_pw pw; - - /* getgrnam, getgrgid */ - - struct winbindd_gr gr; - - uint32_t num_entries; /* getpwent, getgrent */ - struct winbindd_sid { - fstring sid; /* lookupname, [ug]id_to_sid */ - int type; - } sid; - struct winbindd_name { - fstring dom_name; /* lookupsid */ - fstring name; - int type; - } name; - uid_t uid; /* sid_to_uid */ - gid_t gid; /* sid_to_gid */ - struct winbindd_info { - char winbind_separator; - fstring samba_version; - } info; - fstring domain_name; - fstring netbios_name; - fstring dc_name; - - struct auth_reply { - uint32_t nt_status; - fstring nt_status_string; - fstring error_string; - int pam_error; - char user_session_key[16]; - char first_8_lm_hash[8]; - fstring krb5ccname; - uint32_t reject_reason; - uint32_t padding; - struct policy_settings { - uint32_t min_length_password; - uint32_t password_history; - uint32_t password_properties; - uint32_t padding; - SMB_TIME_T expire; - SMB_TIME_T min_passwordage; - } policy; - struct info3_text { - SMB_TIME_T logon_time; - SMB_TIME_T logoff_time; - SMB_TIME_T kickoff_time; - SMB_TIME_T pass_last_set_time; - SMB_TIME_T pass_can_change_time; - SMB_TIME_T pass_must_change_time; - uint32_t logon_count; - uint32_t bad_pw_count; - uint32_t user_rid; - uint32_t group_rid; - uint32_t num_groups; - uint32_t user_flgs; - uint32_t acct_flags; - uint32_t num_other_sids; - fstring dom_sid; - fstring user_name; - fstring full_name; - fstring logon_script; - fstring profile_path; - fstring home_dir; - fstring dir_drive; - fstring logon_srv; - fstring logon_dom; - } info3; - } auth; - struct { - fstring name; - fstring alt_name; - fstring sid; - bool native_mode; - bool active_directory; - bool primary; - } domain_info; - uint32_t sequence_number; - struct { - fstring acct_name; - fstring full_name; - fstring homedir; - fstring shell; - uint32_t primary_gid; - uint32_t group_rid; - } user_info; - struct { - uint32_t auth_blob_len; /* blob in extra_data */ - } ccache_ntlm_auth; - } data; - - /* Variable length return data */ - - union { - SMB_TIME_T padding; - void *data; - } extra_data; -}; - -struct WINBINDD_MEMORY_CREDS { - struct WINBINDD_MEMORY_CREDS *next, *prev; - const char *username; /* lookup key. */ - uid_t uid; - int ref_count; - size_t len; - uint8_t *nt_hash; /* Base pointer for the following 2 */ - uint8_t *lm_hash; - char *pass; -}; - -struct WINBINDD_CCACHE_ENTRY { - struct WINBINDD_CCACHE_ENTRY *next, *prev; - const char *principal_name; - const char *ccname; - const char *service; - const char *username; - const char *realm; - struct WINBINDD_MEMORY_CREDS *cred_ptr; - int ref_count; - uid_t uid; - time_t create_time; - time_t renew_until; - time_t refresh_time; - struct timed_event *event; -}; - -#endif diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c index 8f260eb580..9a9765b564 100644 --- a/source4/winbind/wb_samba3_protocol.c +++ b/source4/winbind/wb_samba3_protocol.c @@ -183,15 +183,18 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call) case WINBINDD_ALLOCATE_UID: case WINBINDD_ALLOCATE_GID: case WINBINDD_SET_MAPPING: + case WINBINDD_REMOVE_MAPPING: case WINBINDD_SET_HWM: case WINBINDD_DOMAIN_INFO: case WINBINDD_SHOW_SEQUENCE: case WINBINDD_WINS_BYIP: case WINBINDD_WINS_BYNAME: case WINBINDD_GETGRLST: + case WINBINDD_DSGETDCNAME: case WINBINDD_INIT_CONNECTION: case WINBINDD_DUAL_SIDS2XIDS: case WINBINDD_DUAL_SET_MAPPING: + case WINBINDD_DUAL_REMOVE_MAPPING: case WINBINDD_DUAL_SET_HWM: case WINBINDD_DUAL_USERINFO: case WINBINDD_DUAL_GETSIDALIASES: -- cgit From 42366bcbbdd42bb9d5821dfcc9dbe71a1eafa330 Mon Sep 17 00:00:00 2001 From: Holger Hetterich Date: Sun, 2 Nov 2008 00:12:32 +0100 Subject: Added a simple tdb integrity check to tdbtool. The command "check" runs traverse on the currently open tdb, and returns the number of entries if the integrity check is successful. --- lib/tdb/tools/tdbtool.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/tdb/tools/tdbtool.c b/lib/tdb/tools/tdbtool.c index d104ccd7c4..1ecad62a3d 100644 --- a/lib/tdb/tools/tdbtool.c +++ b/lib/tdb/tools/tdbtool.c @@ -57,6 +57,7 @@ enum commands { CMD_FIRST, CMD_NEXT, CMD_SYSTEM, + CMD_CHECK, CMD_QUIT, CMD_HELP }; @@ -87,6 +88,7 @@ COMMAND_TABLE cmd_table[] = { {"1", CMD_FIRST}, {"next", CMD_NEXT}, {"n", CMD_NEXT}, + {"check", CMD_CHECK}, {"quit", CMD_QUIT}, {"q", CMD_QUIT}, {"!", CMD_SYSTEM}, @@ -179,7 +181,8 @@ static void help(void) " delete key : delete a record by key\n" " list : print the database hash table and freelist\n" " free : print the database freelist\n" -" ! command : execute system command\n" +" check : check the integrity of an opened database\n" +" ! command : execute system command\n" " 1 | first : print the first record\n" " n | next : print the next record\n" " q | quit : terminate\n" @@ -452,6 +455,27 @@ static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) print_rec(the_tdb, *pkey, dbuf, NULL); } +static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + return 0; +} + +static void check_db(TDB_CONTEXT *the_tdb) +{ + int tdbcount=-1; + if (the_tdb) { + tdbcount = tdb_traverse(the_tdb, test_fn, NULL); + } else { + printf("Error: No database opened!\n"); + } + + if (tdbcount<0) { + printf("Integrity check for the opened database failed.\n"); + } else { + printf("Database integrity is OK and has %d records.\n", tdbcount); + } +} + static int do_command(void) { COMMAND_TABLE *ctp = cmd_table; @@ -552,6 +576,9 @@ static int do_command(void) if (bIterate) next_record(tdb, &iterate_kbuf); return 0; + case CMD_CHECK: + check_db(tdb); + return 0; case CMD_HELP: help(); return 0; -- cgit From 37be72c6c1549195b3fbe5bb1554f5f1cea30894 Mon Sep 17 00:00:00 2001 From: Holger Hetterich Date: Thu, 20 Nov 2008 10:32:14 +0100 Subject: Add an entry for the "check" command to the tdbtool manpage. --- docs-xml/manpages-3/tdbtool.8.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs-xml/manpages-3/tdbtool.8.xml b/docs-xml/manpages-3/tdbtool.8.xml index 3f5dec4ecd..c75059b957 100644 --- a/docs-xml/manpages-3/tdbtool.8.xml +++ b/docs-xml/manpages-3/tdbtool.8.xml @@ -191,6 +191,14 @@ + + + + + Check the integrity of the current database. + + + -- cgit From 9e64ed018e5aa84d802b01953b481fbb07eb00aa Mon Sep 17 00:00:00 2001 From: Karolin Seeger Date: Tue, 16 Dec 2008 15:10:29 +0100 Subject: docs: "acl compatibility" is a global parameter. This fixes bug #5866. Thanks to TAKAHASHI Motonobu for reporting! Karolin --- docs-xml/smbdotconf/vfs/aclcompatibility.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-xml/smbdotconf/vfs/aclcompatibility.xml b/docs-xml/smbdotconf/vfs/aclcompatibility.xml index 7891adc13b..95f42cfe2a 100644 --- a/docs-xml/smbdotconf/vfs/aclcompatibility.xml +++ b/docs-xml/smbdotconf/vfs/aclcompatibility.xml @@ -1,5 +1,5 @@ -- cgit