summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/access.c20
-rw-r--r--source3/lib/data_blob.c2
-rw-r--r--source3/lib/md4.c20
-rw-r--r--source3/lib/memcache.c88
-rw-r--r--source3/lib/netapi/examples/Makefile.in57
-rw-r--r--source3/lib/netapi/examples/getdc/getdc.c (renamed from source3/lib/netapi/joindomain.h)50
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/logo.pngbin0 -> 9329 bytes
-rw-r--r--source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c1347
-rwxr-xr-xsource3/lib/netapi/examples/netdomjoin-gui/samba.icobin0 -> 1406 bytes
-rw-r--r--source3/lib/netapi/examples/netdomjoin/netdomjoin.c107
-rw-r--r--source3/lib/netapi/getdc.c243
-rw-r--r--source3/lib/netapi/joindomain.c432
-rw-r--r--source3/lib/netapi/netapi.c160
-rw-r--r--source3/lib/netapi/netapi.h74
-rw-r--r--source3/lib/netapi/serverinfo.c297
-rw-r--r--source3/lib/secace.c5
-rw-r--r--source3/lib/secacl.c3
-rw-r--r--source3/lib/secdesc.c12
-rw-r--r--source3/lib/sharesec.c10
-rw-r--r--source3/lib/socket_wrapper/socket_wrapper.c4
-rw-r--r--source3/lib/time.c4
-rw-r--r--source3/lib/util_pw.c68
-rw-r--r--source3/lib/util_seaccess.c4
-rw-r--r--source3/lib/util_str.c77
-rw-r--r--source3/lib/winbind_util.c324
25 files changed, 3185 insertions, 223 deletions
diff --git a/source3/lib/access.c b/source3/lib/access.c
index 1e4df83607..6a463446d1 100644
--- a/source3/lib/access.c
+++ b/source3/lib/access.c
@@ -97,13 +97,29 @@ static bool string_match(const char *tok,const char *s)
}
} else if (tok[0] == '@') { /* netgroup: look it up */
#ifdef HAVE_NETGROUP
- static char *mydomain = NULL;
+ DATA_BLOB tmp;
+ char *mydomain = NULL;
char *hostname = NULL;
bool netgroup_ok = false;
- if (!mydomain)
+ if (memcache_lookup(
+ NULL, SINGLETON_CACHE,
+ data_blob_string_const("yp_default_domain"),
+ &tmp)) {
+
+ SMB_ASSERT(tmp.length > 0);
+ mydomain = (tmp.data[0] == '\0')
+ ? NULL : (char *)tmp.data;
+ }
+ else {
yp_get_default_domain(&mydomain);
+ memcache_add(
+ NULL, SINGLETON_CACHE,
+ data_blob_string_const("yp_default_domain"),
+ data_blob_string_const(mydomain?mydomain:""));
+ }
+
if (!mydomain) {
DEBUG(0,("Unable to get default yp domain. "
"Try without it.\n"));
diff --git a/source3/lib/data_blob.c b/source3/lib/data_blob.c
index e64e6a19a1..8bbbc32d7b 100644
--- a/source3/lib/data_blob.c
+++ b/source3/lib/data_blob.c
@@ -128,7 +128,7 @@ DATA_BLOB data_blob_string_const(const char *str)
{
DATA_BLOB blob;
blob.data = CONST_DISCARD(uint8 *, str);
- blob.length = strlen(str);
+ blob.length = strlen(str) + 1;
blob.free = NULL;
return blob;
}
diff --git a/source3/lib/md4.c b/source3/lib/md4.c
index 61d5848aae..bae0091e36 100644
--- a/source3/lib/md4.c
+++ b/source3/lib/md4.c
@@ -24,7 +24,14 @@
It assumes that a int is at least 32 bits long
*/
+#if 0
static uint32 A, B, C, D;
+#else
+#define A (state[0])
+#define B (state[1])
+#define C (state[2])
+#define D (state[3])
+#endif
static uint32 F(uint32 X, uint32 Y, uint32 Z)
{
@@ -52,7 +59,7 @@ static uint32 lshift(uint32 x, int s)
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
/* this applies md4 to 64 byte chunks */
-static void mdfour64(uint32 *M)
+static void mdfour64(uint32_t *state, uint32 *M)
{
int j;
uint32 AA, BB, CC, DD;
@@ -121,6 +128,7 @@ void mdfour(unsigned char *out, const unsigned char *in, int n)
{
unsigned char buf[128];
uint32 M[16];
+ uint32 state[4];
uint32 b = n * 8;
int i;
@@ -131,7 +139,7 @@ void mdfour(unsigned char *out, const unsigned char *in, int n)
while (n > 64) {
copy64(M, in);
- mdfour64(M);
+ mdfour64(state, M);
in += 64;
n -= 64;
}
@@ -144,13 +152,13 @@ void mdfour(unsigned char *out, const unsigned char *in, int n)
if (n <= 55) {
copy4(buf+56, b);
copy64(M, buf);
- mdfour64(M);
+ mdfour64(state, M);
} else {
copy4(buf+120, b);
copy64(M, buf);
- mdfour64(M);
+ mdfour64(state, M);
copy64(M, buf+64);
- mdfour64(M);
+ mdfour64(state, M);
}
for (i=0;i<128;i++)
@@ -161,8 +169,6 @@ void mdfour(unsigned char *out, const unsigned char *in, int n)
copy4(out+4, B);
copy4(out+8, C);
copy4(out+12, D);
-
- A = B = C = D = 0;
}
diff --git a/source3/lib/memcache.c b/source3/lib/memcache.c
index 17630066ae..457586bd68 100644
--- a/source3/lib/memcache.c
+++ b/source3/lib/memcache.c
@@ -20,6 +20,8 @@
#include "memcache.h"
#include "rbtree.h"
+static struct memcache *global_cache;
+
struct memcache_element {
struct rb_node rb_node;
struct memcache_element *prev, *next;
@@ -35,11 +37,38 @@ struct memcache {
size_t max_size;
};
+static void memcache_element_parse(struct memcache_element *e,
+ DATA_BLOB *key, DATA_BLOB *value);
+
+static bool memcache_is_talloc(enum memcache_number n)
+{
+ bool result;
+
+ switch (n) {
+ case GETPWNAM_CACHE:
+ result = true;
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ return result;
+}
+
static int memcache_destructor(struct memcache *cache) {
struct memcache_element *e, *next;
for (e = cache->mru; e != NULL; e = next) {
next = e->next;
+ if (memcache_is_talloc((enum memcache_number)e->n)
+ && (e->valuelength == sizeof(void *))) {
+ DATA_BLOB key, value;
+ void *ptr;
+ memcache_element_parse(e, &key, &value);
+ memcpy(&ptr, value.data, sizeof(ptr));
+ TALLOC_FREE(ptr);
+ }
SAFE_FREE(e);
}
return 0;
@@ -58,6 +87,12 @@ struct memcache *memcache_init(TALLOC_CTX *mem_ctx, size_t max_size)
return result;
}
+void memcache_set_global(struct memcache *cache)
+{
+ TALLOC_FREE(global_cache);
+ global_cache = cache;
+}
+
static struct memcache_element *memcache_node2elem(struct rb_node *node)
{
return (struct memcache_element *)
@@ -119,6 +154,13 @@ bool memcache_lookup(struct memcache *cache, enum memcache_number n,
{
struct memcache_element *e;
+ if (cache == NULL) {
+ cache = global_cache;
+ }
+ if (cache == NULL) {
+ return false;
+ }
+
e = memcache_find(cache, n, key);
if (e == NULL) {
return false;
@@ -141,6 +183,25 @@ bool memcache_lookup(struct memcache *cache, enum memcache_number n,
return true;
}
+void *memcache_lookup_talloc(struct memcache *cache, enum memcache_number n,
+ DATA_BLOB key)
+{
+ DATA_BLOB value;
+ void *result;
+
+ if (!memcache_lookup(cache, n, key, &value)) {
+ return NULL;
+ }
+
+ if (value.length != sizeof(result)) {
+ return NULL;
+ }
+
+ memcpy(&result, value.data, sizeof(result));
+
+ return result;
+}
+
static void memcache_delete_element(struct memcache *cache,
struct memcache_element *e)
{
@@ -172,6 +233,13 @@ void memcache_delete(struct memcache *cache, enum memcache_number n,
{
struct memcache_element *e;
+ if (cache == NULL) {
+ cache = global_cache;
+ }
+ if (cache == NULL) {
+ return;
+ }
+
e = memcache_find(cache, n, key);
if (e == NULL) {
return;
@@ -189,6 +257,13 @@ void memcache_add(struct memcache *cache, enum memcache_number n,
DATA_BLOB cache_key, cache_value;
size_t element_size;
+ if (cache == NULL) {
+ cache = global_cache;
+ }
+ if (cache == NULL) {
+ return;
+ }
+
if (key.length == 0) {
return;
}
@@ -254,10 +329,23 @@ void memcache_add(struct memcache *cache, enum memcache_number n,
memcache_trim(cache);
}
+void memcache_add_talloc(struct memcache *cache, enum memcache_number n,
+ DATA_BLOB key, void *ptr)
+{
+ memcache_add(cache, n, key, data_blob_const(&ptr, sizeof(ptr)));
+}
+
void memcache_flush(struct memcache *cache, enum memcache_number n)
{
struct rb_node *node;
+ if (cache == NULL) {
+ cache = global_cache;
+ }
+ if (cache == NULL) {
+ return;
+ }
+
/*
* Find the smallest element of number n
*/
diff --git a/source3/lib/netapi/examples/Makefile.in b/source3/lib/netapi/examples/Makefile.in
new file mode 100644
index 0000000000..c2f453dedc
--- /dev/null
+++ b/source3/lib/netapi/examples/Makefile.in
@@ -0,0 +1,57 @@
+GTK_FLAGS=`pkg-config gtk+-2.0 --cflags`
+GTK_LIBS=`pkg-config gtk+-2.0 --libs`
+
+KRB5LIBS=@KRB5_LIBS@
+LDAP_LIBS=@LDAP_LIBS@
+LIBS=@LIBS@ -lnetapi
+DEVELOPER_CFLAGS=@DEVELOPER_CFLAGS@
+FLAGS=@CFLAGS@ $(GTK_FLAGS)
+CC=@CC@
+LDFLAGS=@PIE_LDFLAGS@ @LDFLAGS@
+DYNEXP=@DYNEXP@
+
+# Compile a source file.
+COMPILE_CC = $(CC) -I. $(FLAGS) $(PICFLAG) -c $< -o $@
+COMPILE = $(COMPILE_CC)
+
+BINARY_PREREQS = proto_exists bin/.dummy
+
+MAKEDIR = || exec false; \
+ if test -d "$$dir"; then :; else \
+ echo mkdir "$$dir"; \
+ mkdir -p "$$dir" >/dev/null 2>&1 || \
+ test -d "$$dir" || \
+ mkdir "$$dir" || \
+ exec false; fi || exec false
+
+.c.o:
+ @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \
+ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi
+ @echo Compiling $*.c
+ @$(COMPILE) && exit 0;\
+ echo "The following command failed:" 1>&2;\
+ echo "$(COMPILE_CC)" 1>&2;\
+ $(COMPILE_CC) >/dev/null 2>&1
+
+GETDC_OBJ = getdc/getdc.o
+NETDOMJOIN_OBJ = netdomjoin/netdomjoin.o
+NETDOMJOIN_GUI_OBJ = netdomjoin-gui/netdomjoin-gui.o
+
+PROGS = bin/getdc@EXEEXT@ bin/netdomjoin@EXEEXT@ bin/netdomjoin-gui@EXEEXT@
+
+all: $(PROGS)
+
+bin/getdc@EXEEXT@: $(GETDC_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(GETDC_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+
+bin/netdomjoin@EXEEXT@: $(NETDOMJOIN_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) -o $@ $(NETDOMJOIN_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+
+bin/netdomjoin-gui@EXEEXT@: $(NETDOMJOIN_GUI_OBJ)
+ @echo Linking $@
+ @$(CC) $(FLAGS) $(GTK_FLAGS) -o $@ $(NETDOMJOIN_GUI_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(GTK_LIBS)
+
+clean:
+ @rm -f $(PROGS)
diff --git a/source3/lib/netapi/joindomain.h b/source3/lib/netapi/examples/getdc/getdc.c
index 2c71702db7..4f5c5332d5 100644
--- a/source3/lib/netapi/joindomain.h
+++ b/source3/lib/netapi/examples/getdc/getdc.c
@@ -1,6 +1,6 @@
/*
* Unix SMB/CIFS implementation.
- * NetApi Support
+ * GetDCName query
* Copyright (C) Guenther Deschner 2007
*
* This program is free software; you can redistribute it and/or modify
@@ -17,13 +17,41 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-WERROR NetJoinDomain(const char *server,
- const char *domain,
- const char *account_ou,
- const char *account,
- const char *password,
- uint32_t join_options);
-WERROR NetUnjoinDomain(const char *server_name,
- const char *account,
- const char *password,
- uint32_t unjoin_flags);
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+int main(int argc, char **argv)
+{
+ NET_API_STATUS status;
+ struct libnetapi_ctx *ctx = NULL;
+ uint8_t *buffer;
+
+ if (argc < 3) {
+ printf("usage: getdc <hostname> <domain>\n");
+ return -1;
+ }
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ libnetapi_set_username(ctx, "");
+ libnetapi_set_password(ctx, "");
+
+ status = NetGetDCName(argv[1], argv[2], &buffer);
+ if (status != 0) {
+ printf("GetDcName failed with: %s\n", libnetapi_errstr(ctx, status));
+ } else {
+ printf("%s\n", (char *)buffer);
+ }
+
+ libnetapi_free(ctx);
+
+ return status;
+}
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/logo.png b/source3/lib/netapi/examples/netdomjoin-gui/logo.png
new file mode 100644
index 0000000000..6df4ace659
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/logo.png
Binary files differ
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
new file mode 100644
index 0000000000..beb12be8b1
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c
@@ -0,0 +1,1347 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Join Support (gtk + netapi)
+ * Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+
+#include <netapi.h>
+
+#define MAX_CRED_LEN 256
+#define MAX_NETBIOS_NAME_LEN 15
+
+#define SAMBA_ICON_PATH "/usr/share/pixmaps/samba/samba.ico"
+#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
+
+#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
+#define WKSSVC_JOIN_FLAGS_JOIN_TYPE ( 0x00000001 )
+
+#define NetSetupWorkgroupName ( 2 )
+#define NetSetupDomainName ( 3 )
+
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
+
+struct srvsvc_NetSrvInfo1005 {
+ const char *comment;/* [unique,charset(UTF16)] */
+};
+
+static gboolean verbose = FALSE;
+
+typedef struct join_state {
+ struct libnetapi_ctx *ctx;
+ GtkWidget *window_main;
+ GtkWidget *window_parent;
+ GtkWidget *window_do_change;
+ GtkWidget *window_creds_prompt;
+ GtkWidget *entry_account;
+ GtkWidget *entry_password;
+ GtkWidget *entry_domain;
+ GtkWidget *entry_workgroup;
+ GtkWidget *button_ok;
+ GtkWidget *button_apply;
+ GtkWidget *button_ok_creds;
+ GtkWidget *label_reboot;
+ GtkWidget *label_current_name_buffer;
+ GtkWidget *label_current_name_type;
+ GtkWidget *label_full_computer_name;
+ uint16_t name_type_initial;
+ uint16_t name_type_new;
+ char *name_buffer_initial;
+ char *name_buffer_new;
+ char *password;
+ char *account;
+ char *comment;
+ char *comment_new;
+ char *my_fqdn;
+ char *my_dnsdomain;
+ char *my_hostname;
+ uint16_t server_role;
+ gboolean settings_changed;
+ gboolean hostname_changed;
+} join_state;
+
+static void debug(const char *format, ...)
+{
+ va_list args;
+
+ if (!verbose) {
+ return;
+ }
+
+ va_start(args, format);
+ g_vprintf(format, args);
+ va_end(args);
+}
+
+static gboolean callback_delete_event(GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ gtk_main_quit();
+ return FALSE;
+}
+
+static void callback_do_close(GtkWidget *widget,
+ gpointer data)
+{
+ debug("Closing now...\n");
+ gtk_widget_destroy(data);
+}
+
+static void free_join_state(struct join_state *s)
+{
+ SAFE_FREE(s->name_buffer_initial);
+ SAFE_FREE(s->name_buffer_new);
+ SAFE_FREE(s->password);
+ SAFE_FREE(s->account);
+ SAFE_FREE(s->comment);
+ SAFE_FREE(s->comment_new);
+ SAFE_FREE(s->my_fqdn);
+ SAFE_FREE(s->my_dnsdomain);
+ SAFE_FREE(s->my_hostname);
+
+}
+
+static void do_cleanup(struct join_state *state)
+{
+ libnetapi_free(state->ctx);
+ free_join_state(state);
+}
+
+static void callback_apply_description_change(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ NET_API_STATUS status = 0;
+ uint32_t parm_err = 0;
+ struct srvsvc_NetSrvInfo1005 info1005;
+ GtkWidget *dialog;
+
+ info1005.comment = state->comment_new;
+
+ status = NetServerSetInfo(NULL, 1005, (uint8_t *)&info1005, &parm_err);
+ if (status) {
+ debug("NetServerSetInfo failed with: %s\n",
+ libnetapi_errstr(state->ctx, status));
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "Failed to change computer description: %s.",
+ libnetapi_errstr(state->ctx, status));
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+ return;
+ }
+
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
+}
+
+static void callback_do_exit(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *dialog;
+ gint result;
+ struct join_state *state = (struct join_state *)data;
+
+ if (!state->settings_changed) {
+ callback_delete_event(NULL, NULL, NULL);
+ return;
+ }
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ "You must restart your computer before the new settings will take effect.");
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ g_print("would reboot here\n");
+ break;
+ case GTK_RESPONSE_NO:
+ default:
+ break;
+ }
+ gtk_widget_destroy(dialog);
+ gtk_widget_destroy(state->window_main);
+ do_cleanup(state);
+ exit(0);
+}
+
+
+static void callback_do_reboot(GtkWidget *widget,
+ gpointer data,
+ gpointer data2)
+{
+ GtkWidget *dialog;
+ struct join_state *state = (struct join_state *)data2;
+
+ debug("callback_do_reboot\n");
+
+ state->settings_changed = TRUE;
+ dialog = gtk_message_dialog_new(GTK_WINDOW(data),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "You must restart this computer for the changes to take effect.");
+#if 0
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ debug("showing dialog\n");
+ gtk_widget_show(dialog);
+#else
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+#endif
+
+ gtk_label_set_text(GTK_LABEL(state->label_reboot), "Changes will take effect after you restart this computer");
+
+ debug("destroying do_change window\n");
+ gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
+
+ {
+ uint32_t status;
+ const char *buffer;
+ uint16_t type;
+
+ status = NetGetJoinInformation(NULL, &buffer, &type);
+ if (status != 0) {
+ g_print("failed to query status\n");
+ return;
+ }
+
+ debug("got new status: %s\n", buffer);
+#if 0
+ SAFE_FREE(state->name_buffer_new);
+ state->name_buffer_new = strdup(buffer);
+ SAFE_FREE(buffer);
+ state->name_type_new = type;
+#endif
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer), state->name_buffer_new);
+ if (state->name_type_new == 3) {
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Domain:");
+ } else {
+ gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Workgroup:");
+ }
+ }
+}
+
+static void callback_return_username(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_return_username: %s\n", entry_text);
+ SAFE_FREE(state->account);
+ state->account = strdup(entry_text);
+}
+
+static void callback_return_username_and_enter(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_return_username: %s\n", entry_text);
+ SAFE_FREE(state->account);
+ state->account = strdup(entry_text);
+ g_signal_emit_by_name(state->button_ok_creds, "clicked");
+}
+
+static void callback_return_password(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+#ifdef DEBUG_PASSWORD
+ debug("callback_return_password: %s\n", entry_text);
+#else
+ debug("callback_return_password: (not printed)\n");
+#endif
+ SAFE_FREE(state->password);
+ state->password = strdup(entry_text);
+}
+
+static void callback_return_password_and_enter(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text;
+ struct join_state *state = (struct join_state *)data;
+ if (!widget) {
+ return;
+ }
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+#ifdef DEBUG_PASSWORD
+ debug("callback_return_password: %s\n", entry_text);
+#else
+ debug("callback_return_password: (not printed)\n");
+#endif
+ SAFE_FREE(state->password);
+ state->password = strdup(entry_text);
+ g_signal_emit_by_name(state->button_ok_creds, "clicked");
+}
+
+static void callback_do_hostname_change(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *dialog;
+ const char *str = NULL;
+
+ struct join_state *state = (struct join_state *)data;
+
+ switch (state->name_type_initial) {
+ case NetSetupDomainName:
+ str = "To be implemented: call NetRenameMachineInDomain\n";
+ break;
+ case NetSetupWorkgroupName:
+ str = "To be implemented: call SetComputerNameEx\n";
+ break;
+ default:
+ break;
+ }
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ str);
+
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+ gtk_widget_show(dialog);
+}
+
+static void callback_do_join(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *dialog;
+
+ NET_API_STATUS status;
+ const char *err_str = NULL;
+ uint32_t join_flags = 0;
+ uint32_t unjoin_flags = 0;
+ gboolean domain_join = FALSE;
+ gboolean try_unjoin = FALSE;
+ const char *domain_or_workgroup = NULL;
+
+ struct join_state *state = (struct join_state *)data;
+
+ callback_return_username(state->entry_account, state);
+ callback_return_password(state->entry_password, state);
+
+ if (state->window_creds_prompt) {
+ gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
+ }
+
+ if (state->name_type_new == NetSetupDomainName) {
+ domain_join = TRUE;
+ join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+ WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
+ WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
+ domain_or_workgroup = "domain";
+ } else {
+ domain_or_workgroup = "workgroup";
+ }
+
+ if ((state->name_type_initial == NetSetupDomainName) &&
+ (state->name_type_new == NetSetupWorkgroupName)) {
+ try_unjoin = TRUE;
+ unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+ WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
+ }
+
+ debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
+ domain_or_workgroup,
+ state->name_buffer_new,
+ join_flags);
+ if (domain_join) {
+ debug("as %s ", state->account);
+#ifdef DEBUG_PASSWORD
+ debug("with %s ", state->password);
+#endif
+ }
+ debug("\n");
+ if (try_unjoin) {
+
+ debug("callback_do_join: Unjoining\n");
+
+ status = NetUnjoinDomain(NULL,
+ state->account,
+ state->password,
+ unjoin_flags);
+ if (status != 0) {
+ err_str = libnetapi_errstr(state->ctx, status);
+ g_print("callback_do_join: failed to unjoin (%s)\n",
+ err_str);
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "The following error occured attempting to unjoin the %s: \"%s\": %s",
+ domain_or_workgroup,
+ state->name_buffer_new,
+ err_str);
+
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+
+ return;
+ }
+
+ }
+ status = NetJoinDomain(NULL,
+ state->name_buffer_new,
+ NULL,
+ state->account,
+ state->password,
+ join_flags);
+ if (status != 0) {
+ err_str = libnetapi_errstr(state->ctx, status);
+ g_print("callback_do_join: failed to join (%s)\n", err_str);
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "The following error occured attempting to join the %s: \"%s\": %s",
+ domain_or_workgroup,
+ state->name_buffer_new,
+ err_str);
+
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+
+ return;
+ }
+
+ debug("callback_do_join: Successfully joined %s\n",
+ domain_or_workgroup);
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "Welcome to the %s %s.",
+ state->name_buffer_new,
+ domain_or_workgroup);
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ callback_do_reboot(NULL, state->window_parent, state);
+}
+
+static void callback_creds_prompt(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *window;
+ GtkWidget *box1;
+ GtkWidget *bbox;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_creds_prompt:\n");
+
+ state->window_parent = state->window_do_change;
+
+ if (state->hostname_changed) {
+ return callback_do_hostname_change(NULL, state);
+ }
+
+ if ((state->name_type_initial != NetSetupDomainName) &&
+ (state->name_type_new != NetSetupDomainName)) {
+ return callback_do_join(NULL, state);
+ }
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+ gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
+ gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+/* gtk_window_set_icon_name(GTK_WIDGET(window), GTK_STOCK_DIALOG_AUTHENTICATION); */
+ state->window_creds_prompt = window;
+
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(callback_do_close), window);
+
+ gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+ box1 = gtk_vbox_new(FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(window), box1);
+
+ if ((state->name_type_initial == NetSetupDomainName) &&
+ (state->name_type_new == NetSetupWorkgroupName)) {
+ label = gtk_label_new("Enter the name and password of an account with permission to leave the domain.\n");
+ } else {
+ label = gtk_label_new("Enter the name and password of an account with permission to join the domain.\n");
+ }
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+
+ gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+
+ gtk_widget_show(label);
+
+ /* USER NAME */
+ label = gtk_label_new("User name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ state->entry_account = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
+ g_signal_connect(G_OBJECT(state->entry_account), "activate",
+ G_CALLBACK(callback_return_username_and_enter),
+ (gpointer)state);
+ gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
+ 0, GTK_ENTRY(state->entry_account)->text_length);
+ gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_account);
+
+ /* PASSWORD */
+ label = gtk_label_new("Password:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+
+ state->entry_password = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
+ gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
+ g_signal_connect(G_OBJECT(state->entry_password), "activate",
+ G_CALLBACK(callback_return_password_and_enter),
+ (gpointer)state);
+ gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
+ gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
+ 0, GTK_ENTRY(state->entry_password)->text_length);
+ gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_password);
+
+ bbox = gtk_hbutton_box_new();
+ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(box1), bbox);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+ state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
+ gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
+ g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
+ G_CALLBACK(callback_do_join),
+ (gpointer)state);
+ gtk_widget_show(state->button_ok_creds);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback_do_close), (gpointer) window);
+ gtk_widget_show_all(window);
+}
+
+static void callback_enter_hostname_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ char *str = NULL;
+ struct join_state *state = (struct join_state *)data;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
+ if (!entry_text || entry_text[0] == 0) {
+ state->hostname_changed = FALSE;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ if (strcasecmp(state->my_hostname, entry_text) == 0) {
+ state->hostname_changed = FALSE;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ state->hostname_changed = TRUE;
+ if (state->name_type_initial == NetSetupDomainName) {
+ asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+ } else {
+ asprintf(&str, "%s.", entry_text);
+ }
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+ free(str);
+
+ if (state->hostname_changed && str && str[0] != 0 && str[0] != '.') {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+ }
+}
+
+static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ struct join_state *state = (struct join_state *)data;
+ int string_unchanged = 0;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_computer_description_and_unlock: %s\n",
+ entry_text);
+#if 0
+ if (!entry_text || entry_text[0] == 0) {
+ string_unchanged = 1;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
+ FALSE);
+ return;
+ }
+#endif
+ if (entry_text && strcasecmp(state->comment, entry_text) == 0) {
+ string_unchanged = 1;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
+ FALSE);
+ return;
+ }
+
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
+ SAFE_FREE(state->comment_new);
+ state->comment_new = strdup(entry_text);
+
+}
+
+
+static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ struct join_state *state = (struct join_state *)data;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
+ if (!entry_text || entry_text[0] == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+ SAFE_FREE(state->name_buffer_new);
+ state->name_buffer_new = strdup(entry_text);
+ state->name_type_new = NetSetupWorkgroupName;
+}
+
+static void callback_enter_domain_and_unlock(GtkWidget *widget,
+ gpointer data)
+{
+ const gchar *entry_text = NULL;
+ struct join_state *state = (struct join_state *)data;
+
+ entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+ debug("callback_enter_domain_and_unlock: %s\n", entry_text);
+ if (!entry_text || entry_text[0] == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+ SAFE_FREE(state->name_buffer_new);
+ state->name_buffer_new = strdup(entry_text);
+ state->name_type_new = NetSetupDomainName;
+}
+
+static void callback_continue(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
+ g_signal_emit_by_name(state->button_ok, "clicked");
+}
+
+static void callback_apply_continue(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+
+ gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
+ g_signal_emit_by_name(state->button_apply, "clicked");
+}
+
+static void callback_do_join_workgroup(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ debug("callback_do_join_workgroup choosen\n");
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
+ gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
+ callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
+}
+
+static void callback_do_join_domain(GtkWidget *widget,
+ gpointer data)
+{
+ struct join_state *state = (struct join_state *)data;
+ debug("callback_do_join_domain choosen\n");
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
+ gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
+ callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
+}
+
+static void callback_do_change(GtkWidget *widget,
+ gpointer data)
+{
+ GtkWidget *window;
+ GtkWidget *box1;
+ GtkWidget *bbox;
+ GtkWidget *button_workgroup;
+ GtkWidget *button_domain;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *frame_horz;
+ GtkWidget *vbox;
+ GtkWidget *entry;
+ GSList *group;
+
+ struct join_state *state = (struct join_state *)data;
+
+ debug("callback_do_change called\n");
+
+ if (state->server_role == 3) {
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "Domain controller cannot be moved from one domain to another, they must first be demoted. Renaming this domain controller may cause it to become temporarily unavailable to users and computers. For information on renaming domain controllers, including alternate renaming methods, see Help and Support. To continue renaming this domain controller, click OK.");
+ g_signal_connect_swapped(dialog, "response",
+ G_CALLBACK(gtk_widget_destroy),
+ dialog);
+
+ gtk_widget_show(dialog);
+ return;
+ }
+
+ state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500); /* breite * höhe */
+ gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(callback_do_close), window);
+
+ gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+ box1 = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(window), box1);
+
+ label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+ gtk_widget_show(label);
+
+ /* COMPUTER NAME */
+ label = gtk_label_new("Computer name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+ gtk_widget_show(label);
+
+ state->label_full_computer_name = gtk_label_new(NULL);
+ {
+ entry = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(callback_enter_hostname_and_unlock),
+ (gpointer)state);
+ gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
+ gtk_editable_select_region(GTK_EDITABLE(entry),
+ 0, GTK_ENTRY(entry)->text_length);
+
+ gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
+ gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
+ gtk_widget_show(entry);
+ }
+
+ /* FULL COMPUTER NAME */
+ label = gtk_label_new("Full computer name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+ gtk_widget_show(label);
+
+ {
+ const gchar *entry_text;
+ char *str = NULL;
+ entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (state->name_type_initial == NetSetupDomainName) {
+ asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+ } else {
+ asprintf(&str, "%s.", entry_text);
+ }
+ gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+ free(str);
+ gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
+ gtk_box_pack_start(GTK_BOX(box1), state->label_full_computer_name, TRUE, TRUE, 0);
+ gtk_widget_show(state->label_full_computer_name);
+ }
+
+ /* BOX */
+ frame_horz = gtk_frame_new ("Member Of");
+ gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+ gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
+
+ /* TWO ENTRIES */
+ state->entry_workgroup = gtk_entry_new();
+ state->entry_domain = gtk_entry_new();
+
+ /* DOMAIN */
+ button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
+ if (state->name_type_initial == NetSetupDomainName) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(button_domain), "clicked",
+ G_CALLBACK(callback_do_join_domain),
+ (gpointer)state);
+
+ {
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
+ g_signal_connect(G_OBJECT(state->entry_domain), "changed",
+ G_CALLBACK(callback_enter_domain_and_unlock),
+ (gpointer)state);
+ g_signal_connect(G_OBJECT(state->entry_domain), "activate",
+ G_CALLBACK(callback_continue),
+ (gpointer)state);
+ if (state->name_type_initial == NetSetupDomainName) {
+ gtk_entry_set_text(GTK_ENTRY(state->entry_domain), state->name_buffer_initial);
+ gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
+ gtk_widget_set_sensitive(state->entry_domain, TRUE);
+ }
+ gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
+ gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_domain);
+ }
+ gtk_widget_show(button_domain);
+
+ /* WORKGROUP */
+ group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
+ button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
+ if (state->name_type_initial == NetSetupWorkgroupName) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(button_workgroup), "clicked",
+ G_CALLBACK(callback_do_join_workgroup),
+ (gpointer)state);
+ {
+ gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup), MAX_NETBIOS_NAME_LEN);
+ g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
+ G_CALLBACK(callback_enter_workgroup_and_unlock),
+ (gpointer)state);
+ g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
+ G_CALLBACK(callback_continue),
+ (gpointer)state);
+
+ if (state->name_type_initial == NetSetupWorkgroupName) {
+ gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup), state->name_buffer_initial);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
+ gtk_widget_show(state->entry_workgroup);
+ }
+ gtk_widget_show(button_workgroup);
+
+ /* BUTTONS */
+ bbox = gtk_hbutton_box_new();
+ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(box1), bbox);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+ state->window_do_change = window;
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE); /* !!! */
+ gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
+ g_signal_connect(G_OBJECT(state->button_ok), "clicked",
+ G_CALLBACK(callback_creds_prompt),
+ (gpointer)state);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_container_add(GTK_CONTAINER(bbox), button);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback_do_close),
+ (gpointer)window);
+
+ gtk_widget_show_all(window);
+
+}
+
+static void callback_do_about(GtkWidget *widget,
+ gpointer data)
+{
+ GdkPixbuf *logo;
+ GError *error = NULL;
+
+ debug("callback_do_about called\n");
+
+ logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
+ &error);
+ if (logo == NULL) {
+ g_print("failed to load logo from %s: %s\n",
+ SAMBA_IMAGE_PATH, error->message);
+ }
+
+ gtk_show_about_dialog(data,
+ "name", "Samba",
+ "version", "3.2.0pre2-GIT-904a90-test",
+ "copyright", "Copyright Andrew Tridgell and the Samba Team 1992-2007",
+ "website", "http://www.samba.org",
+ "license", "GPLv3",
+ "logo", logo,
+ "comments", "Samba gtk domain join utility",
+ NULL);
+}
+
+static int draw_main_window(struct join_state *state)
+{
+ GtkWidget *window;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *main_vbox;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *image;
+ GtkWidget *table;
+ GtkWidget *entry;
+ GdkPixbuf *icon;
+ GError *error = NULL;
+
+ icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
+ &error);
+ if (icon == NULL) {
+ g_print("failed to load logo from %s : %s\n",
+ SAMBA_ICON_PATH, error->message);
+ }
+
+#if 1
+ image = gtk_image_new_from_file(SAMBA_IMAGE_PATH);
+#else
+ image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
+#endif
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ state->window_main = window;
+
+ gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
+ gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600); /* breite * höhe */
+ gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+ gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+
+ g_signal_connect(G_OBJECT(window), "delete_event",
+ G_CALLBACK(callback_delete_event), NULL);
+
+ gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+ main_vbox = gtk_vbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(window), main_vbox);
+
+#if 0
+ gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
+ gtk_widget_show(image);
+#endif
+ /* Hbox */
+ hbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
+
+ {
+/* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
+ gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
+ gtk_widget_show(image);
+
+ /* Label */
+ label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_widget_set_size_request(GTK_WIDGET(label), 500, 40);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show(label);
+ }
+
+ gtk_widget_show(hbox);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+ gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
+
+ /* Table */
+ table = gtk_table_new(6, 3, TRUE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 5);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 5);
+ gtk_container_add(GTK_CONTAINER(vbox), table);
+
+ {
+ /* Label */
+ label = gtk_label_new("Computer description:");
+/* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+ gtk_widget_show(label);
+
+ state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+
+ /* Entry */
+ entry = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(callback_enter_computer_description_and_unlock),
+ state);
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(callback_apply_continue),
+ (gpointer)state);
+
+ gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
+ gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
+ gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
+ gtk_widget_show(entry);
+ }
+
+ /* Label */
+ label = gtk_label_new("For example: \"Samba \%v\".");
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
+ gtk_widget_show(label);
+
+ /* Label */
+ label = gtk_label_new("Full computer name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
+ gtk_widget_show(label);
+
+ {
+ /* Label */
+ char *str = NULL;
+ if (state->name_type_initial == NetSetupDomainName) {
+ asprintf(&str, "%s.%s", state->my_hostname,
+ state->my_dnsdomain);
+ } else {
+ asprintf(&str, "%s.", state->my_hostname);
+ }
+
+ label = gtk_label_new(str);
+ SAFE_FREE(str);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
+ gtk_widget_show(label);
+ }
+
+ /* Label */
+ if (state->name_type_initial == NetSetupDomainName) {
+ label = gtk_label_new("Domain:");
+ } else {
+ label = gtk_label_new("Workgroup:");
+ }
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
+ gtk_widget_show(label);
+ state->label_current_name_type = label;
+
+ /* Label */
+ label = gtk_label_new(state->name_buffer_initial);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
+ gtk_widget_show(label);
+ state->label_current_name_buffer = label;
+
+ {
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+ label = gtk_label_new("To rename this computer or join a domain, click Change.");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+
+ }
+
+ /* bbox */
+ bbox = gtk_hbutton_box_new();
+ gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+ gtk_container_add(GTK_CONTAINER(hbox), bbox);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+ button = gtk_button_new_with_mnemonic("Ch_ange");
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(callback_do_change),
+ (gpointer)state);
+ gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
+ gtk_widget_show(button);
+
+ /* Label (hidden) */
+ state->label_reboot = gtk_label_new(NULL);
+ gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
+ gtk_widget_show(state->label_reboot);
+
+#if 0
+ gtk_box_pack_start(GTK_BOX(vbox),
+ create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
+ TRUE, TRUE, 5);
+#endif
+ {
+
+ GtkWidget *frame;
+ GtkWidget *bbox2;
+ GtkWidget *button2;
+
+ frame = gtk_frame_new(NULL);
+ bbox2 = gtk_hbutton_box_new();
+
+ gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
+ gtk_container_add(GTK_CONTAINER(frame), bbox2);
+
+ /* Set the appearance of the Button Box */
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
+ gtk_box_set_spacing(GTK_BOX(bbox2), 10);
+ /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
+
+ button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
+
+ button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked",
+ G_CALLBACK(callback_delete_event),
+ window);
+
+ gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
+ g_signal_connect(G_OBJECT(state->button_apply), "clicked",
+ G_CALLBACK(callback_apply_description_change),
+ state);
+ gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
+
+ button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
+ gtk_container_add(GTK_CONTAINER(bbox2), button2);
+ g_signal_connect(G_OBJECT(button2), "clicked",
+ G_CALLBACK(callback_do_about),
+ window);
+
+ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
+ }
+
+ gtk_widget_show_all(window);
+
+ return 0;
+}
+
+static int init_join_state(struct join_state **state)
+{
+ struct join_state *s;
+
+ s = malloc(sizeof(struct join_state));
+ if (!s) {
+ return -1;
+ }
+
+ memset(s, '\0', sizeof(struct join_state));
+
+ *state = s;
+
+ return 0;
+}
+
+static int initialize_join_state(struct join_state *state,
+ const char *debug_level)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status = 0;
+
+ status = libnetapi_init(&ctx);
+ if (status) {
+ return status;
+ }
+
+ if (debug_level) {
+ libnetapi_set_debuglevel(ctx, debug_level);
+ }
+
+ {
+ char my_hostname[HOST_NAME_MAX];
+ const char *p = NULL;
+ if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
+ return -1;
+ }
+
+ state->my_fqdn = strdup(my_hostname);
+ if (!state->my_fqdn) {
+ return -1;
+ }
+
+ p = strchr(my_hostname, '.');
+ if (p) {
+ my_hostname[strlen(my_hostname) - strlen(p)] = '\0';
+ state->my_hostname = strdup(my_hostname);
+ if (!state->my_hostname) {
+ return -1;
+ }
+ p++;
+ state->my_dnsdomain = strdup(p);
+ if (!state->my_dnsdomain) {
+ return -1;
+ }
+ }
+ }
+
+ {
+ const char *buffer = NULL;
+ uint16_t type = 0;
+ status = NetGetJoinInformation(NULL, &buffer, &type);
+ if (status) {
+ return status;
+ }
+ state->name_buffer_initial = (char *)buffer;
+ state->name_type_initial = type;
+ }
+
+ {
+ struct srvsvc_NetSrvInfo1005 *info1005 = NULL;
+ uint8_t *buffer = NULL;
+
+ status = NetServerGetInfo(NULL, 1005, &buffer);
+ if (status) {
+ return status;
+ }
+
+ info1005 = (struct srvsvc_NetSrvInfo1005 *)buffer;
+
+ state->comment = strdup(info1005->comment);
+ if (!state->comment) {
+ return -1;
+ }
+ }
+#if 0
+ {
+ struct srvsvc_NetSrvInfo100 *info100 = NULL;
+ uint8_t *buffer = NULL;
+
+ status = NetServerGetInfo(NULL, 100, &buffer);
+ if (status) {
+ return status;
+ }
+
+ info100 = (struct srvsvc_NetSrvInfo100 *)buffer;
+
+ state->comment = strdup(info100->comment);
+ if (!state->comment) {
+ return -1;
+ }
+ }
+#endif
+
+ state->ctx = ctx;
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ GOptionContext *context = NULL;
+ static const char *debug_level = NULL;
+ struct join_state *state = NULL;
+ GError *error = NULL;
+ int ret = 0;
+
+ static GOptionEntry entries[] = {
+ { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
+ { NULL }
+ };
+
+ context = g_option_context_new("- Samba domain join utility");
+ g_option_context_add_main_entries(context, entries, NULL);
+/* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
+ g_option_context_add_group(context, gtk_get_option_group(TRUE));
+ g_option_context_parse(context, &argc, &argv, &error);
+
+ gtk_init(&argc, &argv);
+ g_set_application_name("Samba");
+
+ ret = init_join_state(&state);
+ if (ret) {
+ return ret;
+ }
+
+ ret = initialize_join_state(state, debug_level);
+ if (ret) {
+ return ret;
+ }
+
+ draw_main_window(state);
+
+ gtk_main();
+
+ do_cleanup(state);
+
+ return 0;
+}
diff --git a/source3/lib/netapi/examples/netdomjoin-gui/samba.ico b/source3/lib/netapi/examples/netdomjoin-gui/samba.ico
new file mode 100755
index 0000000000..b70c9590de
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin-gui/samba.ico
Binary files differ
diff --git a/source3/lib/netapi/examples/netdomjoin/netdomjoin.c b/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
new file mode 100644
index 0000000000..e8b529927f
--- /dev/null
+++ b/source3/lib/netapi/examples/netdomjoin/netdomjoin.c
@@ -0,0 +1,107 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Join Support (cmdline + netapi)
+ * Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netapi.h>
+
+char *get_string_param(const char *param)
+{
+ char *p;
+
+ p = strchr(param, '=');
+ if (!p) {
+ return NULL;
+ }
+
+ return (p+1);
+}
+
+int main(int argc, char **argv)
+{
+ NET_API_STATUS status;
+ const char *server_name = NULL;
+ const char *domain_name = NULL;
+ const char *account_ou = NULL;
+ const char *Account = NULL;
+ const char *password = NULL;
+ uint32_t join_flags = 3;
+ struct libnetapi_ctx *ctx = NULL;
+ int i;
+
+ status = libnetapi_init(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ if (argc < 2) {
+ printf("usage: netdomjoin\n");
+ printf("\t[hostname=HOSTNAME] [domain=DOMAIN] <ou=OU> <usero=USERO> <passwordo=PASSWORDO> <userd=USERD> <passwordd=PASSWORDD>\n");
+ return 0;
+ }
+
+ if (argc > 2) {
+ server_name = argv[1];
+ }
+
+ for (i=0; i<argc; i++) {
+ if (strncasecmp(argv[i], "ou", strlen("ou")) == 0) {
+ account_ou = get_string_param(argv[i]);
+ }
+ if (strncasecmp(argv[i], "domain", strlen("domain"))== 0) {
+ domain_name = get_string_param(argv[i]);
+ }
+ if (strncasecmp(argv[i], "userd", strlen("userd"))== 0) {
+ Account = get_string_param(argv[i]);
+ }
+ if (strncasecmp(argv[i], "passwordd", strlen("passwordd"))== 0) {
+ password = get_string_param(argv[i]);
+ }
+ if (strncasecmp(argv[i], "usero", strlen("usero"))== 0) {
+ const char *str = NULL;
+ str = get_string_param(argv[i]);
+ libnetapi_set_username(ctx, str);
+ }
+ if (strncasecmp(argv[i], "passwordo", strlen("passwordo"))== 0) {
+ const char *str = NULL;
+ str = get_string_param(argv[i]);
+ libnetapi_set_password(ctx, str);
+ }
+ }
+
+ status = NetJoinDomain(server_name,
+ domain_name,
+ account_ou,
+ Account,
+ password,
+ join_flags);
+ if (status != 0) {
+ printf("Join failed with: %s\n", libnetapi_errstr(ctx, status));
+ } else {
+ printf("Successfully joined\n");
+ }
+
+ libnetapi_free(ctx);
+
+ return status;
+}
diff --git a/source3/lib/netapi/getdc.c b/source3/lib/netapi/getdc.c
new file mode 100644
index 0000000000..85a0ae52ef
--- /dev/null
+++ b/source3/lib/netapi/getdc.c
@@ -0,0 +1,243 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi GetDC Support
+ * Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "lib/netapi/netapi.h"
+#include "libnet/libnet.h"
+
+#if 0
+#include "librpc/gen_ndr/cli_netlogon.h"
+#endif
+
+NTSTATUS rpccli_netr_GetDcName(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const char *logon_server,
+ const char *domainname,
+ const char **dcname);
+NTSTATUS rpccli_netr_GetAnyDCName(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const char *logon_server,
+ const char *domainname,
+ const char **dcname,
+ WERROR *werror);
+
+static WERROR NetGetDCNameLocal(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+static WERROR NetGetDCNameRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ status = cli_full_connection(&cli, NULL, server_name,
+ NULL, 0,
+ "IPC$", "IPC",
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON,
+ &status);
+ if (!pipe_cli) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ };
+
+#if 0
+ werr = rpccli_netr_GetDcName(pipe_cli, ctx,
+ server_name,
+ domain_name,
+ (const char **)&buffer);
+#else
+ werr = rpccli_netlogon_getdcname(pipe_cli, ctx,
+ server_name,
+ domain_name,
+ (char **)buffer);
+#endif
+ done:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return werr;
+}
+
+static WERROR libnetapi_NetGetDCName(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+ return NetGetDCNameLocal(ctx,
+ server_name,
+ domain_name,
+ buffer);
+ }
+
+ return NetGetDCNameRemote(ctx,
+ server_name,
+ domain_name,
+ buffer);
+}
+
+NET_API_STATUS NetGetDCName(const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetGetDCName(ctx,
+ server_name,
+ domain_name,
+ buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
+
+static WERROR NetGetAnyDCNameLocal(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+static WERROR NetGetAnyDCNameRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ status = cli_full_connection(&cli, NULL, server_name,
+ NULL, 0,
+ "IPC$", "IPC",
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON,
+ &status);
+ if (!pipe_cli) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ };
+
+#if 0
+ status = rpccli_netr_GetAnyDCName(pipe_cli, ctx,
+ server_name,
+ domain_name,
+ (const char **)&buffer,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+#else
+ werr = rpccli_netlogon_getanydcname(pipe_cli, ctx,
+ server_name,
+ domain_name,
+ (char **)buffer);
+#endif
+ done:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return werr;
+
+}
+
+static WERROR libnetapi_NetGetAnyDCName(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+ return NetGetAnyDCNameLocal(ctx,
+ server_name,
+ domain_name,
+ buffer);
+ }
+
+ return NetGetAnyDCNameRemote(ctx,
+ server_name,
+ domain_name,
+ buffer);
+}
+
+NET_API_STATUS NetGetAnyDCName(const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetGetAnyDCName(ctx,
+ server_name,
+ domain_name,
+ buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
diff --git a/source3/lib/netapi/joindomain.c b/source3/lib/netapi/joindomain.c
index 210763174e..e3d5eada02 100644
--- a/source3/lib/netapi/joindomain.c
+++ b/source3/lib/netapi/joindomain.c
@@ -19,56 +19,96 @@
#include "includes.h"
-extern const char *opt_user_name;
-extern const char *opt_workgroup;
-extern const char *opt_password;
-
-WERROR NetJoinDomain(const char *server_name,
- const char *domain_name,
- const char *account_ou,
- const char *Account,
- const char *password,
- uint32_t join_flags)
+#include "lib/netapi/netapi.h"
+#include "libnet/libnet.h"
+
+static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx,
+ const char *server_name,
+ const char *domain_name,
+ const char *account_ou,
+ const char *Account,
+ const char *password,
+ uint32_t join_flags)
{
- TALLOC_CTX *mem_ctx = NULL;
- struct cli_state *cli = NULL;
- struct rpc_pipe_client *pipe_cli = NULL;
- struct wkssvc_PasswordBuffer encrypted_password;
- NTSTATUS status;
+ struct libnet_JoinCtx *r = NULL;
WERROR werr;
- unsigned int old_timeout = 0;
- ZERO_STRUCT(encrypted_password);
+ werr = libnet_init_JoinCtx(mem_ctx, &r);
+ W_ERROR_NOT_OK_RETURN(werr);
- mem_ctx = talloc_init("NetJoinDomain");
- if (!mem_ctx) {
- werr = WERR_NOMEM;
- goto done;
+ if (!domain_name) {
+ return WERR_INVALID_PARAM;
}
- if (!server_name || is_myname_or_ipaddr(server_name)) {
- werr = WERR_NOT_SUPPORTED;
- goto done;
+ r->in.domain_name = talloc_strdup(mem_ctx, domain_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.domain_name);
+
+ if (join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
+ NTSTATUS status;
+ struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
+ uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
+ DS_WRITABLE_REQUIRED |
+ DS_RETURN_DNS_NAME;
+ status = DsGetDcName(mem_ctx, NULL, domain_name,
+ NULL, NULL, flags, &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+ r->in.server_name = talloc_strdup(mem_ctx, info->domain_controller_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
}
- if (!domain_name) {
- werr = WERR_INVALID_PARAM;
- goto done;
+ if (account_ou) {
+ r->in.account_ou = talloc_strdup(mem_ctx, account_ou);
+ W_ERROR_HAVE_NO_MEMORY(r->in.account_ou);
+ }
+
+ if (Account) {
+ r->in.admin_account = talloc_strdup(mem_ctx, Account);
+ W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
}
+ if (password) {
+ r->in.password = talloc_strdup(mem_ctx, password);
+ W_ERROR_HAVE_NO_MEMORY(r->in.password);
+ }
+
+ r->in.join_flags = join_flags;
+ r->in.modify_config = true;
+
+ return libnet_Join(mem_ctx, r);
+}
+
+static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ const char *account_ou,
+ const char *Account,
+ const char *password,
+ uint32_t join_flags)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ struct wkssvc_PasswordBuffer encrypted_password;
+ NTSTATUS status;
+ WERROR werr;
+ unsigned int old_timeout = 0;
+
+ ZERO_STRUCT(encrypted_password);
+
status = cli_full_connection(&cli, NULL, server_name,
NULL, 0,
"IPC$", "IPC",
- opt_user_name, opt_workgroup,
- opt_password, 0, Undefined, NULL);
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- old_timeout = cli_set_timeout(cli, 60000);
-
pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
&status);
if (!pipe_cli) {
@@ -77,7 +117,7 @@ WERROR NetJoinDomain(const char *server_name,
};
if (password) {
- encode_wkssvc_join_password_buffer(mem_ctx,
+ encode_wkssvc_join_password_buffer(ctx,
password,
&cli->user_session_key,
&encrypted_password);
@@ -85,7 +125,7 @@ WERROR NetJoinDomain(const char *server_name,
old_timeout = cli_set_timeout(cli, 60000);
- status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, mem_ctx,
+ status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
server_name, domain_name,
account_ou, Account,
&encrypted_password,
@@ -100,17 +140,140 @@ WERROR NetJoinDomain(const char *server_name,
cli_set_timeout(cli, old_timeout);
cli_shutdown(cli);
}
- TALLOC_FREE(mem_ctx);
return werr;
}
-WERROR NetUnjoinDomain(const char *server_name,
- const char *account,
- const char *password,
- uint32_t unjoin_flags)
+static WERROR libnetapi_NetJoinDomain(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *domain_name,
+ const char *account_ou,
+ const char *Account,
+ const char *password,
+ uint32_t join_flags)
+{
+ if (!domain_name) {
+ return WERR_INVALID_PARAM;
+ }
+
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+
+ return NetJoinDomainLocal(ctx,
+ server_name,
+ domain_name,
+ account_ou,
+ Account,
+ password,
+ join_flags);
+ }
+
+ return NetJoinDomainRemote(ctx,
+ server_name,
+ domain_name,
+ account_ou,
+ Account,
+ password,
+ join_flags);
+}
+
+NET_API_STATUS NetJoinDomain(const char *server_name,
+ const char *domain_name,
+ const char *account_ou,
+ const char *Account,
+ const char *password,
+ uint32_t join_flags)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetJoinDomain(ctx,
+ server_name,
+ domain_name,
+ account_ou,
+ Account,
+ password,
+ join_flags);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
+
+static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
+ const char *server_name,
+ const char *account,
+ const char *password,
+ uint32_t unjoin_flags)
+{
+ struct libnet_UnjoinCtx *r = NULL;
+ struct dom_sid domain_sid;
+ WERROR werr;
+
+ if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
+ return WERR_SETUP_NOT_JOINED;
+ }
+
+ werr = libnet_init_UnjoinCtx(mem_ctx, &r);
+ W_ERROR_NOT_OK_RETURN(werr);
+
+ if (server_name) {
+ r->in.server_name = talloc_strdup(mem_ctx, server_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ } else {
+
+ NTSTATUS status;
+ const char *domain = NULL;
+ struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
+ uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
+ DS_WRITABLE_REQUIRED |
+ DS_IS_FLAT_NAME |
+ DS_RETURN_DNS_NAME;
+ if (lp_realm()) {
+ domain = lp_realm();
+ } else {
+ domain = lp_workgroup();
+ }
+ status = DsGetDcName(mem_ctx, NULL, domain,
+ NULL, NULL, flags, &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+ r->in.server_name = talloc_strdup(mem_ctx, info->domain_controller_name);
+ W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
+ }
+
+ if (account) {
+ r->in.admin_account = talloc_strdup(mem_ctx, account);
+ W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
+ }
+
+ if (password) {
+ r->in.password = talloc_strdup(mem_ctx, password);
+ W_ERROR_HAVE_NO_MEMORY(r->in.password);
+ }
+
+ r->in.unjoin_flags = unjoin_flags;
+ r->in.modify_config = true;
+
+ r->in.domain_sid = &domain_sid;
+
+ return libnet_Unjoin(mem_ctx, r);
+
+}
+
+static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *account,
+ const char *password,
+ uint32_t unjoin_flags)
{
- TALLOC_CTX *mem_ctx = NULL;
struct cli_state *cli = NULL;
struct rpc_pipe_client *pipe_cli = NULL;
struct wkssvc_PasswordBuffer encrypted_password;
@@ -120,30 +283,19 @@ WERROR NetUnjoinDomain(const char *server_name,
ZERO_STRUCT(encrypted_password);
- mem_ctx = talloc_init("NetUnjoinDomain");
- if (!mem_ctx) {
- werr = WERR_NOMEM;
- goto done;
- }
-
- if (!server_name || is_myname_or_ipaddr(server_name)) {
- werr = WERR_NOT_SUPPORTED;
- goto done;
- }
-
status = cli_full_connection(&cli, NULL, server_name,
NULL, 0,
"IPC$", "IPC",
- opt_user_name, opt_workgroup,
- opt_password, 0, Undefined, NULL);
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
if (!NT_STATUS_IS_OK(status)) {
werr = ntstatus_to_werror(status);
goto done;
}
- old_timeout = cli_set_timeout(cli, 60000);
-
pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
&status);
if (!pipe_cli) {
@@ -152,7 +304,7 @@ WERROR NetUnjoinDomain(const char *server_name,
};
if (password) {
- encode_wkssvc_join_password_buffer(mem_ctx,
+ encode_wkssvc_join_password_buffer(ctx,
password,
&cli->user_session_key,
&encrypted_password);
@@ -160,7 +312,7 @@ WERROR NetUnjoinDomain(const char *server_name,
old_timeout = cli_set_timeout(cli, 60000);
- status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, mem_ctx,
+ status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
server_name,
account,
&encrypted_password,
@@ -176,7 +328,173 @@ WERROR NetUnjoinDomain(const char *server_name,
cli_set_timeout(cli, old_timeout);
cli_shutdown(cli);
}
- TALLOC_FREE(mem_ctx);
return werr;
}
+
+static WERROR libnetapi_NetUnjoinDomain(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char *account,
+ const char *password,
+ uint32_t unjoin_flags)
+{
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+
+ return NetUnjoinDomainLocal(ctx,
+ server_name,
+ account,
+ password,
+ unjoin_flags);
+ }
+
+ return NetUnjoinDomainRemote(ctx,
+ server_name,
+ account,
+ password,
+ unjoin_flags);
+}
+
+NET_API_STATUS NetUnjoinDomain(const char *server_name,
+ const char *account,
+ const char *password,
+ uint32_t unjoin_flags)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetUnjoinDomain(ctx,
+ server_name,
+ account,
+ password,
+ unjoin_flags);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
+
+static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char **name_buffer,
+ uint16_t *name_type)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ status = cli_full_connection(&cli, NULL, server_name,
+ NULL, 0,
+ "IPC$", "IPC",
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
+ &status);
+ if (!pipe_cli) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ };
+
+ status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
+ server_name,
+ name_buffer,
+ (enum wkssvc_NetJoinStatus *)name_type,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return werr;
+}
+
+static WERROR NetGetJoinInformationLocal(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char **name_buffer,
+ uint16_t *name_type)
+{
+ if ((lp_security() == SEC_ADS) && lp_realm()) {
+ *name_buffer = SMB_STRDUP(lp_realm());
+ } else {
+ *name_buffer = SMB_STRDUP(lp_workgroup());
+ }
+ if (!*name_buffer) {
+ return WERR_NOMEM;
+ }
+
+ switch (lp_server_role()) {
+ case ROLE_DOMAIN_MEMBER:
+ case ROLE_DOMAIN_PDC:
+ case ROLE_DOMAIN_BDC:
+ *name_type = NetSetupDomainName;
+ break;
+ case ROLE_STANDALONE:
+ default:
+ *name_type = NetSetupWorkgroupName;
+ break;
+ }
+
+ return WERR_OK;
+}
+
+static WERROR libnetapi_NetGetJoinInformation(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ const char **name_buffer,
+ uint16_t *name_type)
+{
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+ return NetGetJoinInformationLocal(ctx,
+ server_name,
+ name_buffer,
+ name_type);
+ }
+
+ return NetGetJoinInformationRemote(ctx,
+ server_name,
+ name_buffer,
+ name_type);
+}
+
+NET_API_STATUS NetGetJoinInformation(const char *server_name,
+ const char **name_buffer,
+ uint16_t *name_type)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetGetJoinInformation(ctx,
+ server_name,
+ name_buffer,
+ name_type);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c
new file mode 100644
index 0000000000..032798d0f9
--- /dev/null
+++ b/source3/lib/netapi/netapi.c
@@ -0,0 +1,160 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "lib/netapi/netapi.h"
+
+extern bool AllowDebugChange;
+
+struct libnetapi_ctx *stat_ctx = NULL;
+TALLOC_CTX *frame = NULL;
+static bool libnetapi_initialized = false;
+
+NET_API_STATUS libnetapi_init(struct libnetapi_ctx **context)
+{
+ struct libnetapi_ctx *ctx = NULL;
+
+ if (stat_ctx && libnetapi_initialized) {
+ *context = stat_ctx;
+ return W_ERROR_V(WERR_OK);
+ }
+
+ frame = talloc_stackframe();
+
+ ctx = talloc_zero(frame, struct libnetapi_ctx);
+ if (!ctx) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_NOMEM);
+ }
+
+ DEBUGLEVEL = 0;
+ setup_logging("libnetapi", true);
+
+ dbf = x_stderr;
+ x_setbuf(x_stderr, NULL);
+ AllowDebugChange = false;
+
+ load_case_tables();
+
+ if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, false)) {
+ TALLOC_FREE(frame);
+ return W_ERROR_V(WERR_GENERAL_FAILURE);
+ }
+
+ AllowDebugChange = true;
+
+ init_names();
+ load_interfaces();
+ reopen_logs();
+
+ BlockSignals(True, SIGPIPE);
+
+ libnetapi_initialized = true;
+
+ *context = stat_ctx = ctx;
+
+ return W_ERROR_V(WERR_OK);
+}
+
+NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx)
+{
+ if (stat_ctx) {
+ *ctx = stat_ctx;
+ return W_ERROR_V(WERR_OK);
+ }
+
+ return libnetapi_init(ctx);
+}
+
+NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx)
+{
+ gfree_names();
+ gfree_loadparm();
+ gfree_case_tables();
+ gfree_charcnv();
+ gfree_interfaces();
+
+ TALLOC_FREE(ctx);
+ TALLOC_FREE(frame);
+
+ gfree_debugsyms();
+
+ return W_ERROR_V(WERR_OK);
+}
+
+NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx,
+ const char *debuglevel)
+{
+ AllowDebugChange = true;
+ ctx->debuglevel = debuglevel;
+ if (!debug_parse_levels(debuglevel)) {
+ return W_ERROR_V(WERR_GENERAL_FAILURE);
+ }
+ return W_ERROR_V(WERR_OK);
+}
+
+NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx,
+ const char **debuglevel)
+{
+ *debuglevel = ctx->debuglevel;
+ return W_ERROR_V(WERR_OK);
+}
+
+NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx,
+ const char *username)
+{
+ TALLOC_FREE(ctx->username);
+ ctx->username = talloc_strdup(ctx, username);
+ if (!ctx->username) {
+ return W_ERROR_V(WERR_NOMEM);
+ }
+ return W_ERROR_V(WERR_OK);
+}
+
+NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx,
+ const char *password)
+{
+ TALLOC_FREE(ctx->password);
+ ctx->password = talloc_strdup(ctx, password);
+ if (!ctx->password) {
+ return W_ERROR_V(WERR_NOMEM);
+ }
+ return W_ERROR_V(WERR_OK);
+}
+
+NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx,
+ const char *workgroup)
+{
+ TALLOC_FREE(ctx->workgroup);
+ ctx->workgroup = talloc_strdup(ctx, workgroup);
+ if (!ctx->workgroup) {
+ return W_ERROR_V(WERR_NOMEM);
+ }
+ return W_ERROR_V(WERR_OK);
+}
+
+const char *libnetapi_errstr(struct libnetapi_ctx *ctx,
+ NET_API_STATUS status)
+{
+ if (status & 0xc0000000) {
+ return get_friendly_nt_error_msg(NT_STATUS(status));
+ }
+
+ return get_friendly_werror_msg(W_ERROR(status));
+}
diff --git a/source3/lib/netapi/netapi.h b/source3/lib/netapi/netapi.h
new file mode 100644
index 0000000000..0dd6d95ceb
--- /dev/null
+++ b/source3/lib/netapi/netapi.h
@@ -0,0 +1,74 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Support
+ * Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_NETAPI_H__
+#define __LIB_NETAPI_H__
+
+#define NET_API_STATUS uint32_t
+
+struct libnetapi_ctx {
+ const char *debuglevel;
+ char *username;
+ char *workgroup;
+ char *password;
+};
+
+NET_API_STATUS libnetapi_init(struct libnetapi_ctx **ctx);
+NET_API_STATUS libnetapi_getctx(struct libnetapi_ctx **ctx);
+NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx);
+NET_API_STATUS libnetapi_set_debuglevel(struct libnetapi_ctx *ctx, const char *debuglevel);
+NET_API_STATUS libnetapi_get_debuglevel(struct libnetapi_ctx *ctx, const char **debuglevel);
+NET_API_STATUS libnetapi_set_username(struct libnetapi_ctx *ctx, const char *username);
+NET_API_STATUS libnetapi_set_password(struct libnetapi_ctx *ctx, const char *password);
+NET_API_STATUS libnetapi_set_workgroup(struct libnetapi_ctx *ctx, const char *workgroup);
+const char *libnetapi_errstr(struct libnetapi_ctx *ctx, NET_API_STATUS status);
+
+/* wkssvc */
+NET_API_STATUS NetJoinDomain(const char *server,
+ const char *domain,
+ const char *account_ou,
+ const char *account,
+ const char *password,
+ uint32_t join_options);
+NET_API_STATUS NetUnjoinDomain(const char *server_name,
+ const char *account,
+ const char *password,
+ uint32_t unjoin_flags);
+NET_API_STATUS NetGetJoinInformation(const char *server_name,
+ const char **name_buffer,
+ uint16_t *name_type);
+
+/* srvsvc */
+NET_API_STATUS NetServerGetInfo(const char *server_name,
+ uint32_t level,
+ uint8_t **buffer);
+NET_API_STATUS NetServerSetInfo(const char *server_name,
+ uint32_t level,
+ uint8_t *buffer,
+ uint32_t *parm_error);
+
+/* netlogon */
+NET_API_STATUS NetGetDCName(const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer);
+NET_API_STATUS NetGetAnyDCName(const char *server_name,
+ const char *domain_name,
+ uint8_t **buffer);
+
+#endif
diff --git a/source3/lib/netapi/serverinfo.c b/source3/lib/netapi/serverinfo.c
new file mode 100644
index 0000000000..276a98c15e
--- /dev/null
+++ b/source3/lib/netapi/serverinfo.c
@@ -0,0 +1,297 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * NetApi Server Support
+ * Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+
+#include "lib/netapi/netapi.h"
+#include "libnet/libnet.h"
+
+static WERROR NetServerGetInfoLocal_1005(struct libnetapi_ctx *ctx,
+ uint8_t **buffer)
+{
+ struct srvsvc_NetSrvInfo1005 info1005;
+
+ info1005.comment = lp_serverstring();
+ *buffer = (uint8_t *)talloc_memdup(ctx, &info1005, sizeof(info1005));
+ if (!*buffer) {
+ return WERR_NOMEM;
+ }
+
+ return WERR_OK;
+}
+
+static WERROR NetServerGetInfoLocal(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ uint32_t level,
+ uint8_t **buffer)
+{
+ switch (level) {
+ case 1005:
+ return NetServerGetInfoLocal_1005(ctx, buffer);
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ return WERR_UNKNOWN_LEVEL;
+}
+
+static WERROR NetServerGetInfoRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ uint32_t level,
+ uint8_t **buffer)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ union srvsvc_NetSrvInfo info;
+
+ status = cli_full_connection(&cli, NULL, server_name,
+ NULL, 0,
+ "IPC$", "IPC",
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC,
+ &status);
+ if (!pipe_cli) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ };
+
+ status = rpccli_srvsvc_NetSrvGetInfo(pipe_cli, ctx,
+ server_name,
+ level,
+ &info,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ *buffer = (uint8_t *)&info;
+
+ done:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return werr;
+}
+
+static WERROR libnetapi_NetServerGetInfo(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ uint32_t level,
+ uint8_t **buffer)
+{
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+ return NetServerGetInfoLocal(ctx,
+ server_name,
+ level,
+ buffer);
+ }
+
+ return NetServerGetInfoRemote(ctx,
+ server_name,
+ level,
+ buffer);
+
+}
+
+NET_API_STATUS NetServerGetInfo(const char *server_name,
+ uint32_t level,
+ uint8_t **buffer)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetServerGetInfo(ctx,
+ server_name,
+ level,
+ buffer);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
+
+static WERROR NetServerSetInfoLocal_1005(struct libnetapi_ctx *ctx,
+ uint8_t *buffer,
+ uint32_t *parm_error)
+{
+ struct srvsvc_NetSrvInfo1005 *info1005;
+
+ if (!buffer) {
+ *parm_error = 1005; /* sure here ? */
+ return WERR_INVALID_PARAM;
+ }
+
+ info1005 = (struct srvsvc_NetSrvInfo1005 *)buffer;
+
+ if (!info1005->comment) {
+ *parm_error = 1005;
+ return WERR_INVALID_PARAM;
+ }
+
+ if (!lp_include_registry_globals()) {
+ return WERR_NOT_SUPPORTED;
+ }
+
+ return libnet_smbconf_set_global_param(ctx,
+ "server string",
+ info1005->comment);
+}
+
+static WERROR NetServerSetInfoLocal(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ uint32_t level,
+ uint8_t *buffer,
+ uint32_t *parm_error)
+{
+ switch (level) {
+ case 1005:
+ return NetServerSetInfoLocal_1005(ctx, buffer, parm_error);
+ default:
+ return WERR_UNKNOWN_LEVEL;
+ }
+
+ return WERR_UNKNOWN_LEVEL;
+}
+
+static WERROR NetServerSetInfoRemote(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ uint32_t level,
+ uint8_t *buffer,
+ uint32_t *parm_error)
+{
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+ union srvsvc_NetSrvInfo info;
+
+ status = cli_full_connection(&cli, NULL, server_name,
+ NULL, 0,
+ "IPC$", "IPC",
+ ctx->username,
+ ctx->workgroup,
+ ctx->password,
+ 0, Undefined, NULL);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC,
+ &status);
+ if (!pipe_cli) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ };
+
+ switch (level) {
+ case 1005:
+ info.info1005 = (struct srvsvc_NetSrvInfo1005 *)buffer;
+ break;
+ default:
+ werr = WERR_NOT_SUPPORTED;
+ goto done;
+ }
+
+ status = rpccli_srvsvc_NetSrvSetInfo(pipe_cli, ctx,
+ server_name,
+ level,
+ info,
+ parm_error,
+ &werr);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (cli) {
+ cli_shutdown(cli);
+ }
+
+ return werr;
+}
+
+static WERROR libnetapi_NetServerSetInfo(struct libnetapi_ctx *ctx,
+ const char *server_name,
+ uint32_t level,
+ uint8_t *buffer,
+ uint32_t *parm_error)
+{
+ if (!server_name || is_myname_or_ipaddr(server_name)) {
+ return NetServerSetInfoLocal(ctx,
+ server_name,
+ level,
+ buffer,
+ parm_error);
+ }
+
+ return NetServerSetInfoRemote(ctx,
+ server_name,
+ level,
+ buffer,
+ parm_error);
+}
+
+
+NET_API_STATUS NetServerSetInfo(const char *server_name,
+ uint32_t level,
+ uint8_t *buffer,
+ uint32_t *parm_error)
+{
+ struct libnetapi_ctx *ctx = NULL;
+ NET_API_STATUS status;
+ WERROR werr;
+
+ status = libnetapi_getctx(&ctx);
+ if (status != 0) {
+ return status;
+ }
+
+ werr = libnetapi_NetServerSetInfo(ctx,
+ server_name,
+ level,
+ buffer,
+ parm_error);
+ if (!W_ERROR_IS_OK(werr)) {
+ return W_ERROR_V(werr);
+ }
+
+ return 0;
+}
diff --git a/source3/lib/secace.c b/source3/lib/secace.c
index 9e533a5a28..90ecc342cd 100644
--- a/source3/lib/secace.c
+++ b/source3/lib/secace.c
@@ -54,7 +54,8 @@ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
Sets up a SEC_ACE structure.
********************************************************************/
-void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, uint32 mask, uint8 flag)
+void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, enum security_ace_type type,
+ uint32 mask, uint8 flag)
{
t->type = type;
t->flags = flag;
@@ -83,7 +84,7 @@ NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **pp_new, SEC_ACE *old, unsign
for (i = 0; i < *num - 1; i ++)
sec_ace_copy(&(*pp_new)[i], &old[i]);
- (*pp_new)[i].type = 0;
+ (*pp_new)[i].type = SEC_ACE_TYPE_ACCESS_ALLOWED;
(*pp_new)[i].flags = 0;
(*pp_new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid);
(*pp_new)[i].access_mask = mask;
diff --git a/source3/lib/secacl.c b/source3/lib/secacl.c
index 328bc1b4b4..5e82242e1b 100644
--- a/source3/lib/secacl.c
+++ b/source3/lib/secacl.c
@@ -26,7 +26,8 @@
Create a SEC_ACL structure.
********************************************************************/
-SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
+SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, enum security_acl_revision revision,
+ int num_aces, SEC_ACE *ace_list)
{
SEC_ACL *dst;
int i;
diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c
index 4a9785009b..123c3bcc9b 100644
--- a/source3/lib/secdesc.c
+++ b/source3/lib/secdesc.c
@@ -182,7 +182,9 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU
Creates a SEC_DESC structure
********************************************************************/
-SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
+SEC_DESC *make_sec_desc(TALLOC_CTX *ctx,
+ enum security_descriptor_revision revision,
+ uint16 type,
const DOM_SID *owner_sid, const DOM_SID *grp_sid,
SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
{
@@ -329,8 +331,9 @@ NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid,
SEC_ACL *dacl, size_t *sd_size)
{
- return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
- owner_sid, grp_sid, NULL, dacl, sd_size);
+ return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
+ SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
+ dacl, sd_size);
}
/*******************************************************************
@@ -557,7 +560,8 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
correct. Perhaps the user and group should be passed in as
parameters by the caller? */
- sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
+ sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
+ SEC_DESC_SELF_RELATIVE,
parent_ctr->owner_sid,
parent_ctr->group_sid,
parent_ctr->sacl,
diff --git a/source3/lib/sharesec.c b/source3/lib/sharesec.c
index b3b000579f..0027a8813a 100644
--- a/source3/lib/sharesec.c
+++ b/source3/lib/sharesec.c
@@ -92,7 +92,9 @@ SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def
init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
- psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize);
+ psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
+ SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
+ psa, psize);
}
if (!psd) {
@@ -291,7 +293,7 @@ bool parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd)
uint32 s_access;
DOM_SID sid;
char *sidstr;
- uint8 type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+ enum security_ace_type type = SEC_ACE_TYPE_ACCESS_ALLOWED;
if (!next_token_talloc(ctx, &pacl, &sidstr, ":")) {
DEBUG(0,("parse_usershare_acl: malformed usershare acl looking "
@@ -339,7 +341,9 @@ bool parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd)
}
if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, num_aces, ace_list)) != NULL) {
- psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, &sd_size);
+ psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
+ SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
+ psa, &sd_size);
}
if (!psd) {
diff --git a/source3/lib/socket_wrapper/socket_wrapper.c b/source3/lib/socket_wrapper/socket_wrapper.c
index 3a72c5a74a..5b8052e5ed 100644
--- a/source3/lib/socket_wrapper/socket_wrapper.c
+++ b/source3/lib/socket_wrapper/socket_wrapper.c
@@ -571,8 +571,8 @@ static const char *socket_wrapper_pcap_file(void)
{
static int initialized = 0;
static const char *s = NULL;
- static const struct swrap_file_hdr h;
- static const struct swrap_packet p;
+ static const struct swrap_file_hdr h = { 0, };
+ static const struct swrap_packet p = { { 0, }, { { 0, }, { { 0, } } } };
if (initialized == 1) {
return s;
diff --git a/source3/lib/time.c b/source3/lib/time.c
index 5301e3a55a..f98e03197f 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -1382,7 +1382,7 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
d = (double)(t);
d *= 1.0e7;
- *nt = d;
+ *nt = (NTTIME)d;
/* convert to a negative value */
*nt=~*nt;
@@ -1443,7 +1443,7 @@ const char *display_time(NTTIME nttime)
low = ~(nttime & 0xFFFFFFFF);
low = low/(1000*1000*10);
- sec=high+low;
+ sec=(int)(high+low);
days=sec/(60*60*24);
hours=(sec - (days*60*60*24)) / (60*60);
diff --git a/source3/lib/util_pw.c b/source3/lib/util_pw.c
index 1973626d84..428378505f 100644
--- a/source3/lib/util_pw.c
+++ b/source3/lib/util_pw.c
@@ -37,74 +37,36 @@ struct passwd *tcopy_passwd(TALLOC_CTX *mem_ctx, const struct passwd *from)
return ret;
}
-#define PWNAMCACHE_SIZE 4
-static struct passwd **pwnam_cache = NULL;
-
-static void init_pwnam_cache(void)
-{
- if (pwnam_cache != NULL)
- return;
-
- pwnam_cache = TALLOC_ZERO_ARRAY(NULL, struct passwd *,
- PWNAMCACHE_SIZE);
- if (pwnam_cache == NULL) {
- smb_panic("Could not init pwnam_cache");
- }
-
- return;
-}
-
void flush_pwnam_cache(void)
{
- TALLOC_FREE(pwnam_cache);
- pwnam_cache = NULL;
- init_pwnam_cache();
+ memcache_flush(NULL, GETPWNAM_CACHE);
}
struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name)
{
- int i;
-
- struct passwd *temp;
+ struct passwd *temp, *cached;
- init_pwnam_cache();
-
- for (i=0; i<PWNAMCACHE_SIZE; i++) {
- if ((pwnam_cache[i] != NULL) &&
- (strcmp(name, pwnam_cache[i]->pw_name) == 0)) {
- DEBUG(10, ("Got %s from pwnam_cache\n", name));
- return tcopy_passwd(mem_ctx, pwnam_cache[i]);
- }
+ temp = (struct passwd *)memcache_lookup_talloc(
+ NULL, GETPWNAM_CACHE, data_blob_string_const(name));
+ if (temp != NULL) {
+ return tcopy_passwd(mem_ctx, temp);
}
temp = sys_getpwnam(name);
-
- if (!temp) {
-#if 0
- if (errno == ENOMEM) {
- /* what now? */
- }
-#endif
+ if (temp == NULL) {
return NULL;
}
- for (i=0; i<PWNAMCACHE_SIZE; i++) {
- if (pwnam_cache[i] == NULL)
- break;
+ cached = tcopy_passwd(NULL, temp);
+ if (cached == NULL) {
+ /*
+ * Just don't add this into the cache, ignore the failure
+ */
+ return temp;
}
- if (i == PWNAMCACHE_SIZE)
- i = rand() % PWNAMCACHE_SIZE;
-
- if (pwnam_cache[i] != NULL) {
- /* Remove this old cache entry, from the cache. We
- * use talloc_unlink here because we want to be very
- * clear which referece we are removing */
- talloc_unlink(pwnam_cache, pwnam_cache[i]);
- }
-
- pwnam_cache[i] = tcopy_passwd(pwnam_cache, temp);
-
+ memcache_add_talloc(NULL, GETPWNAM_CACHE, data_blob_string_const(name),
+ cached);
return tcopy_passwd(mem_ctx, temp);
}
diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c
index 0481eea5f0..87e70bb95b 100644
--- a/source3/lib/util_seaccess.c
+++ b/source3/lib/util_seaccess.c
@@ -350,7 +350,9 @@ NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
return NT_STATUS_NO_MEMORY;
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ if ((*psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
+ SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
+ psa, sd_size)) == NULL)
return NT_STATUS_NO_MEMORY;
return NT_STATUS_OK;
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index ee76e33de8..7e21fe1195 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -137,83 +137,6 @@ bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
}
/**
-This is like next_token but is not re-entrant and "remembers" the first
-parameter so you can pass NULL. This is useful for user interface code
-but beware the fact that it is not re-entrant!
-**/
-
-static const char *last_ptr=NULL;
-
-bool next_token_nr_talloc(TALLOC_CTX *ctx,
- const char **ptr,
- char **pp_buff,
- const char *sep)
-{
- bool ret;
- if (!ptr) {
- ptr = &last_ptr;
- }
-
- ret = next_token_talloc(ctx, ptr, pp_buff, sep);
- last_ptr = *ptr;
- return ret;
-}
-
-void set_first_token(char *ptr)
-{
- last_ptr = ptr;
-}
-
-/**
- Convert list of tokens to array; dependent on above routine.
- Uses last_ptr from above - bit of a hack.
-**/
-
-char **toktocliplist(int *ctok, const char *sep)
-{
- char *s=(char *)last_ptr;
- int ictok=0;
- char **ret, **iret;
-
- if (!sep)
- sep = " \t\n\r";
-
- while(*s && strchr_m(sep,*s))
- s++;
-
- /* nothing left? */
- if (!*s)
- return(NULL);
-
- do {
- ictok++;
- while(*s && (!strchr_m(sep,*s)))
- s++;
- while(*s && strchr_m(sep,*s))
- *s++=0;
- } while(*s);
-
- *ctok=ictok;
- s=(char *)last_ptr;
-
- if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
- return NULL;
-
- while(ictok--) {
- *iret++=s;
- if (ictok > 0) {
- while(*s++)
- ;
- while(!*s)
- s++;
- }
- }
-
- ret[*ctok] = NULL;
- return ret;
-}
-
-/**
* Case insensitive string compararison.
*
* iconv does not directly give us a way to compare strings in
diff --git a/source3/lib/winbind_util.c b/source3/lib/winbind_util.c
new file mode 100644
index 0000000000..f4e7ab19e8
--- /dev/null
+++ b/source3/lib/winbind_util.c
@@ -0,0 +1,324 @@
+/*
+ Unix SMB/CIFS implementation.
+ Winbind Utility functions
+
+ Copyright (C) Gerald (Jerry) Carter 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+#if defined(WITH_WINBIND)
+
+#include "nsswitch/libwbclient/wbclient.h"
+
+/* Call winbindd to convert a name to a sid */
+
+bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
+ enum lsa_SidType *name_type)
+{
+ struct wbcDomainSid dom_sid;
+ wbcErr result;
+ enum wbcSidType type;
+
+ result = wbcLookupName(dom_name, name, &dom_sid, &type);
+ if (result != WBC_ERR_SUCCESS)
+ return False;
+
+ memcpy(sid, &dom_sid, sizeof(DOM_SID));
+ *name_type = (enum lsa_SidType)type;
+
+ return True;
+}
+
+/* Call winbindd to convert sid to name */
+
+bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ const char **domain, const char **name,
+ enum lsa_SidType *name_type)
+{
+ struct wbcDomainSid dom_sid;
+ wbcErr result;
+ enum wbcSidType type;
+ char *domain_name = NULL;
+ char *account_name = NULL;
+
+ memcpy(&dom_sid, sid, sizeof(dom_sid));
+
+ result = wbcLookupSid(&dom_sid, &domain_name, &account_name, &type);
+ if (result != WBC_ERR_SUCCESS)
+ return False;
+
+ /* Copy out result */
+
+ if (domain) {
+ *domain = talloc_strdup(mem_ctx, domain_name);
+ }
+ if (name) {
+ *name = talloc_strdup(mem_ctx, account_name);
+ }
+ *name_type = (enum lsa_SidType)type;
+
+ DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
+ sid_string_dbg(sid), domain_name, account_name));
+
+ SAFE_FREE(domain_name);
+ SAFE_FREE(account_name);
+
+ if ((domain && !*domain) || (name && !*name)) {
+ DEBUG(0,("winbind_lookup_sid: talloc() failed!\n"));
+ return False;
+ }
+
+
+ return True;
+}
+
+/* Ping winbindd to see it is alive */
+
+bool winbind_ping(void)
+{
+ wbcErr result = wbcPing();
+
+ return (result == WBC_ERR_SUCCESS);
+}
+
+/* Call winbindd to convert SID to uid */
+
+bool winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
+{
+ struct wbcDomainSid dom_sid;
+ wbcErr result;
+
+ memcpy(&dom_sid, sid, sizeof(dom_sid));
+
+ result = wbcSidToUid(&dom_sid, puid);
+ if (result != WBC_ERR_SUCCESS)
+ return False;
+
+ return (result == WBC_ERR_SUCCESS);
+}
+
+/* Call winbindd to convert uid to sid */
+
+bool winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
+{
+ struct wbcDomainSid dom_sid;
+ wbcErr result;
+
+ result = wbcUidToSid(uid, &dom_sid);
+ if (result == WBC_ERR_SUCCESS) {
+ memcpy(sid, &dom_sid, sizeof(DOM_SID));
+ } else {
+ sid_copy(sid, &global_sid_NULL);
+ }
+
+ return (result == WBC_ERR_SUCCESS);
+}
+
+/* Call winbindd to convert SID to gid */
+
+bool winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
+{
+ struct wbcDomainSid dom_sid;
+ wbcErr result;
+
+ memcpy(&dom_sid, sid, sizeof(dom_sid));
+
+ result = wbcSidToGid(&dom_sid, pgid);
+ if (result != WBC_ERR_SUCCESS)
+ return False;
+
+ return (result == WBC_ERR_SUCCESS);
+}
+
+/* Call winbindd to convert gid to sid */
+
+bool winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
+{
+ struct wbcDomainSid dom_sid;
+ wbcErr result;
+
+ result = wbcGidToSid(gid, &dom_sid);
+ if (result == WBC_ERR_SUCCESS) {
+ memcpy(sid, &dom_sid, sizeof(DOM_SID));
+ } else {
+ sid_copy(sid, &global_sid_NULL);
+ }
+
+ return (result == WBC_ERR_SUCCESS);
+}
+
+/* Check for a trusted domain */
+
+wbcErr wb_is_trusted_domain(const char *domain)
+{
+ wbcErr result;
+ struct wbcDomainInfo *info = NULL;
+
+ result = wbcDomainInfo(domain, &info);
+
+ if (WBC_ERROR_IS_OK(result)) {
+ wbcFreeMemory(info);
+ }
+
+ return result;
+}
+
+/* Lookup a set of rids in a given domain */
+
+bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids, uint32 *rids,
+ const char **domain_name,
+ const char ***names, enum lsa_SidType **types)
+{
+ const char *dom_name = NULL;
+ const char **namelist = NULL;
+ enum wbcSidType *name_types = NULL;
+ struct wbcDomainSid dom_sid;
+ wbcErr ret;
+ int i;
+
+ memcpy(&dom_sid, domain_sid, sizeof(struct wbcDomainSid));
+
+ ret = wbcLookupRids(&dom_sid, num_rids, rids,
+ &dom_name, &namelist, &name_types);
+ if (ret != WBC_ERR_SUCCESS)
+ return False;
+
+ *domain_name = talloc_strdup(mem_ctx, dom_name);
+ *names = TALLOC_ARRAY(mem_ctx, const char*, num_rids);
+ *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids);
+
+ for(i=0; i<num_rids; i++) {
+ (*names)[i] = talloc_strdup(names, namelist[i]);
+ (*types)[i] = (enum lsa_SidType)name_types[i];
+
+ free(CONST_DISCARD(char*, namelist[i]));
+ }
+ free(namelist);
+ free(name_types);
+
+ return True;
+}
+
+/* Ask Winbind to allocate a new uid for us */
+
+bool winbind_allocate_uid(uid_t *uid)
+{
+ wbcErr ret;
+
+ ret = wbcAllocateUid(uid);
+
+ return (ret == WBC_ERR_SUCCESS);
+}
+
+/* Ask Winbind to allocate a new gid for us */
+
+bool winbind_allocate_gid(gid_t *gid)
+{
+ wbcErr ret;
+
+ ret = wbcAllocateGid(gid);
+
+ return (ret == WBC_ERR_SUCCESS);
+}
+
+#else /* WITH_WINBIND */
+
+bool winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
+ enum lsa_SidType *name_type)
+{
+ return False;
+}
+
+/* Call winbindd to convert sid to name */
+
+bool winbind_lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+ const char **domain, const char **name,
+ enum lsa_SidType *name_type)
+{
+ return False;
+}
+
+/* Ping winbindd to see it is alive */
+
+bool winbind_ping(void)
+{
+ return False;
+}
+
+/* Call winbindd to convert SID to uid */
+
+bool winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
+{
+ return False;
+}
+
+/* Call winbindd to convert uid to sid */
+
+bool winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
+{
+ return False;
+}
+
+/* Call winbindd to convert SID to gid */
+
+bool winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
+{
+ return False;
+}
+
+/* Call winbindd to convert gid to sid */
+
+bool winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
+{
+ return False;
+}
+
+/* Check for a trusted domain */
+
+wbcErr wb_is_trusted_domain(const char *domain)
+{
+ return WBC_ERR_UNKNOWN_FAILURE;
+}
+
+/* Lookup a set of rids in a given domain */
+
+bool winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+ const DOM_SID *domain_sid,
+ int num_rids, uint32 *rids,
+ const char **domain_name,
+ const char ***names, enum lsa_SidType **types)
+{
+ return False;
+}
+
+/* Ask Winbind to allocate a new uid for us */
+
+bool winbind_allocate_uid(uid_t *uid)
+{
+ return False;
+}
+
+/* Ask Winbind to allocate a new gid for us */
+
+bool winbind_allocate_gid(gid_t *gid)
+{
+ return False;
+}
+
+#endif /* WITH_WINBIND */