2
* Unix SMB/CIFS implementation.
3
* Join Support (gtk + netapi)
4
* Copyright (C) Guenther Deschner 2007-2008
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, see <http://www.gnu.org/licenses/>.
22
#include <sys/types.h>
30
#include <glib/gprintf.h>
34
#define MAX_CRED_LEN 256
35
#define MAX_NETBIOS_NAME_LEN 15
37
#define SAMBA_ICON_PATH "/usr/share/pixmaps/samba/samba.ico"
38
#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
39
#define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
41
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
43
static gboolean verbose = FALSE;
45
typedef struct join_state {
46
struct libnetapi_ctx *ctx;
47
GtkWidget *window_main;
48
GtkWidget *window_parent;
49
GtkWidget *window_do_change;
50
GtkWidget *window_creds_prompt;
51
GtkWidget *entry_account;
52
GtkWidget *entry_password;
53
GtkWidget *entry_domain;
54
GtkWidget *entry_ou_list;
55
GtkWidget *entry_workgroup;
57
GtkWidget *button_apply;
58
GtkWidget *button_ok_creds;
59
GtkWidget *button_get_ous;
60
GtkWidget *label_reboot;
61
GtkWidget *label_current_name_buffer;
62
GtkWidget *label_current_name_type;
63
GtkWidget *label_full_computer_name;
64
GtkWidget *label_winbind;
65
uint16_t name_type_initial;
66
uint16_t name_type_new;
67
char *name_buffer_initial;
68
char *name_buffer_new;
77
gboolean settings_changed;
78
gboolean hostname_changed;
79
uint32_t stored_num_ous;
80
char *target_hostname;
84
static void callback_creds_prompt(GtkWidget *widget,
86
const char *label_string,
90
static void debug(const char *format, ...)
98
va_start(args, format);
99
g_vprintf(format, args);
103
static gboolean callback_delete_event(GtkWidget *widget,
111
static void callback_do_close_data(GtkWidget *widget,
114
debug("callback_do_close_data called\n");
117
gtk_widget_destroy(GTK_WIDGET(data));
121
static void callback_do_close_widget(GtkWidget *widget,
124
debug("callback_do_close_widget called\n");
127
gtk_widget_destroy(widget);
131
static void callback_do_freeauth(GtkWidget *widget,
134
struct join_state *state = (struct join_state *)data;
136
debug("callback_do_freeauth called\n");
138
SAFE_FREE(state->account);
139
SAFE_FREE(state->password);
141
if (state->window_creds_prompt) {
142
gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
143
state->window_creds_prompt = NULL;
147
static void callback_do_freeauth_and_close(GtkWidget *widget,
150
struct join_state *state = (struct join_state *)data;
152
debug("callback_do_freeauth_and_close called\n");
154
SAFE_FREE(state->account);
155
SAFE_FREE(state->password);
157
if (state->window_creds_prompt) {
158
gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
159
state->window_creds_prompt = NULL;
161
if (state->window_do_change) {
162
gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
163
state->window_do_change = NULL;
167
static void free_join_state(struct join_state *s)
169
SAFE_FREE(s->name_buffer_initial);
170
SAFE_FREE(s->name_buffer_new);
171
SAFE_FREE(s->password);
172
SAFE_FREE(s->account);
173
SAFE_FREE(s->comment);
174
SAFE_FREE(s->comment_new);
175
SAFE_FREE(s->my_fqdn);
176
SAFE_FREE(s->my_dnsdomain);
177
SAFE_FREE(s->my_hostname);
180
static void do_cleanup(struct join_state *state)
182
libnetapi_free(state->ctx);
183
free_join_state(state);
186
static void callback_apply_description_change(GtkWidget *widget,
189
struct join_state *state = (struct join_state *)data;
190
NET_API_STATUS status = 0;
191
uint32_t parm_err = 0;
192
struct SERVER_INFO_1005 info1005;
195
info1005.sv1005_comment = state->comment_new;
197
status = NetServerSetInfo(state->target_hostname,
199
(uint8_t *)&info1005,
202
debug("NetServerSetInfo failed with: %s\n",
203
libnetapi_errstr(status));
204
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
205
GTK_DIALOG_DESTROY_WITH_PARENT,
208
"Failed to change computer description: %s.",
209
libnetapi_get_error_string(state->ctx, status));
210
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
211
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
213
g_signal_connect_swapped(dialog, "response",
214
G_CALLBACK(gtk_widget_destroy),
217
gtk_widget_show(dialog);
221
gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
224
static void callback_do_exit(GtkWidget *widget,
231
struct join_state *state = (struct join_state *)data;
233
if (!state->settings_changed) {
234
callback_delete_event(NULL, NULL, NULL);
239
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
240
GTK_DIALOG_DESTROY_WITH_PARENT,
241
GTK_MESSAGE_QUESTION,
243
"You must restart your computer before the new settings will take effect.");
244
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
245
result = gtk_dialog_run(GTK_DIALOG(dialog));
247
case GTK_RESPONSE_YES:
248
g_print("would reboot here\n");
250
case GTK_RESPONSE_NO:
255
gtk_widget_destroy(GTK_WIDGET(dialog));
258
if (state->window_main) {
259
gtk_widget_destroy(GTK_WIDGET(state->window_main));
260
state->window_main = NULL;
267
static void callback_do_reboot(GtkWidget *widget,
272
struct join_state *state = (struct join_state *)data2;
274
debug("callback_do_reboot\n");
276
state->settings_changed = TRUE;
277
dialog = gtk_message_dialog_new(GTK_WINDOW(data),
278
GTK_DIALOG_DESTROY_WITH_PARENT,
281
"You must restart this computer for the changes to take effect.");
282
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
283
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
285
g_signal_connect_swapped(dialog, "response",
286
G_CALLBACK(gtk_widget_destroy),
289
debug("showing dialog\n");
290
gtk_widget_show(dialog);
292
gtk_dialog_run(GTK_DIALOG(dialog));
293
gtk_widget_destroy(GTK_WIDGET(dialog));
296
gtk_label_set_text(GTK_LABEL(state->label_reboot),
297
"Changes will take effect after you restart this computer");
299
debug("destroying do_change window\n");
300
gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
307
status = NetGetJoinInformation(state->target_hostname,
311
g_print("failed to query status\n");
315
debug("got new status: %s\n", buffer);
317
SAFE_FREE(state->name_buffer_new);
318
state->name_buffer_new = strdup(buffer);
319
state->name_type_new = type;
320
state->name_buffer_initial = strdup(buffer);
321
state->name_type_initial = type;
322
NetApiBufferFree((void *)buffer);
324
gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
325
state->name_buffer_new);
326
if (state->name_type_new == NetSetupDomainName) {
327
gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
330
gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
336
static void callback_return_username(GtkWidget *widget,
339
const gchar *entry_text;
340
struct join_state *state = (struct join_state *)data;
341
debug("callback_return_username called\n");
345
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
349
debug("callback_return_username: %s\n", entry_text);
350
SAFE_FREE(state->account);
351
state->account = strdup(entry_text);
354
static void callback_return_username_and_enter(GtkWidget *widget,
357
const gchar *entry_text;
358
struct join_state *state = (struct join_state *)data;
362
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
366
debug("callback_return_username_and_enter: %s\n", entry_text);
367
SAFE_FREE(state->account);
368
state->account = strdup(entry_text);
369
g_signal_emit_by_name(state->button_ok_creds, "clicked");
372
static void callback_return_password(GtkWidget *widget,
375
const gchar *entry_text;
376
struct join_state *state = (struct join_state *)data;
377
debug("callback_return_password called\n");
381
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
385
#ifdef DEBUG_PASSWORD
386
debug("callback_return_password: %s\n", entry_text);
388
debug("callback_return_password: (not printed)\n");
390
SAFE_FREE(state->password);
391
state->password = strdup(entry_text);
394
static void callback_return_password_and_enter(GtkWidget *widget,
397
const gchar *entry_text;
398
struct join_state *state = (struct join_state *)data;
402
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
406
#ifdef DEBUG_PASSWORD
407
debug("callback_return_password_and_enter: %s\n", entry_text);
409
debug("callback_return_password_and_enter: (not printed)\n");
411
SAFE_FREE(state->password);
412
state->password = strdup(entry_text);
413
g_signal_emit_by_name(state->button_ok_creds, "clicked");
416
static void callback_do_storeauth(GtkWidget *widget,
419
struct join_state *state = (struct join_state *)data;
421
debug("callback_do_storeauth called\n");
423
SAFE_FREE(state->account);
424
SAFE_FREE(state->password);
426
callback_return_username(state->entry_account, (gpointer)state);
427
callback_return_password(state->entry_password, (gpointer)state);
429
if (state->window_creds_prompt) {
430
gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
431
state->window_creds_prompt = NULL;
435
static void callback_continue(GtkWidget *widget,
438
struct join_state *state = (struct join_state *)data;
440
gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
441
g_signal_emit_by_name(state->button_ok, "clicked");
444
static void callback_do_storeauth_and_continue(GtkWidget *widget,
447
callback_do_storeauth(widget, data);
448
callback_continue(NULL, data);
451
static void callback_do_storeauth_and_scan(GtkWidget *widget,
454
struct join_state *state = (struct join_state *)data;
455
callback_do_storeauth(widget, data);
456
g_signal_emit_by_name(state->button_get_ous, "clicked");
459
static void callback_do_hostname_change(GtkWidget *widget,
463
const char *str = NULL;
465
struct join_state *state = (struct join_state *)data;
467
switch (state->name_type_initial) {
468
case NetSetupDomainName: {
470
NET_API_STATUS status;
474
newname = strdup(gtk_label_get_text(GTK_LABEL(state->label_full_computer_name)));
479
p = strchr(newname, '.');
484
if (!state->account || !state->password) {
485
debug("callback_do_hostname_change: no creds yet\n");
486
callback_creds_prompt(NULL, state,
487
"Enter the name and password of an account with permission to change a computer name in a the domain.",
488
callback_do_storeauth_and_continue);
491
if (!state->account || !state->password) {
492
debug("callback_do_hostname_change: still no creds???\n");
496
status = NetRenameMachineInDomain(state->target_hostname,
500
NETSETUP_ACCT_CREATE);
502
/* we renamed the machine in the domain */
506
str = libnetapi_get_error_string(state->ctx, status);
508
str = "To be implemented: call NetRenameMachineInDomain\n";
512
case NetSetupWorkgroupName:
513
str = "To be implemented: call SetComputerNameEx\n";
519
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
520
GTK_DIALOG_DESTROY_WITH_PARENT,
525
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
526
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
527
g_signal_connect_swapped(dialog, "response",
528
G_CALLBACK(gtk_widget_destroy),
530
gtk_widget_show(dialog);
533
static void callback_creds_prompt(GtkWidget *widget,
535
const char *label_string,
544
struct join_state *state = (struct join_state *)data;
546
debug("callback_creds_prompt\n");
548
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
549
gtk_window_set_modal(GTK_WINDOW(window), TRUE);
551
gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
552
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
553
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
554
gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
555
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
556
gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_do_change));
557
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
559
g_signal_connect(G_OBJECT(window), "delete_event",
560
G_CALLBACK(callback_do_close_widget), NULL);
562
state->window_creds_prompt = window;
563
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
565
box1 = gtk_vbox_new(FALSE, 0);
567
gtk_container_add(GTK_CONTAINER(window), box1);
569
label = gtk_label_new(label_string);
570
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
571
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
573
gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
575
gtk_widget_show(label);
578
label = gtk_label_new("User name:");
579
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
580
gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
581
gtk_widget_show(label);
583
state->entry_account = gtk_entry_new();
584
gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
585
g_signal_connect(G_OBJECT(state->entry_account), "activate",
586
G_CALLBACK(callback_return_username_and_enter),
588
gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
589
0, GTK_ENTRY(state->entry_account)->text_length);
590
gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
591
gtk_widget_show(state->entry_account);
594
label = gtk_label_new("Password:");
595
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
596
gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
597
gtk_widget_show(label);
599
state->entry_password = gtk_entry_new();
600
gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
601
gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
602
g_signal_connect(G_OBJECT(state->entry_password), "activate",
603
G_CALLBACK(callback_return_password_and_enter),
605
gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
606
gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
607
0, GTK_ENTRY(state->entry_password)->text_length);
608
gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
609
gtk_widget_show(state->entry_password);
612
bbox = gtk_hbutton_box_new();
613
gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
614
gtk_container_add(GTK_CONTAINER(box1), bbox);
615
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
616
gtk_box_set_spacing(GTK_BOX(bbox), 10);
618
state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
619
gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
620
gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
621
g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
624
gtk_widget_show(state->button_ok_creds);
626
button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
627
gtk_container_add(GTK_CONTAINER(bbox), button);
628
g_signal_connect(G_OBJECT(button), "clicked",
629
G_CALLBACK(callback_do_freeauth),
631
gtk_widget_show_all(window);
634
static void callback_do_join(GtkWidget *widget,
639
NET_API_STATUS status;
640
const char *err_str = NULL;
641
uint32_t join_flags = 0;
642
uint32_t unjoin_flags = 0;
643
gboolean domain_join = FALSE;
644
gboolean try_unjoin = FALSE;
645
gboolean join_creds_required = TRUE;
646
gboolean unjoin_creds_required = TRUE;
647
const char *new_workgroup_type = NULL;
648
const char *initial_workgroup_type = NULL;
649
const char *account_ou = NULL;
651
struct join_state *state = (struct join_state *)data;
653
if (state->hostname_changed) {
654
callback_do_hostname_change(NULL, state);
658
switch (state->name_type_initial) {
659
case NetSetupWorkgroupName:
660
initial_workgroup_type = "workgroup";
662
case NetSetupDomainName:
663
initial_workgroup_type = "domain";
669
switch (state->name_type_new) {
670
case NetSetupWorkgroupName:
671
new_workgroup_type = "workgroup";
673
case NetSetupDomainName:
674
new_workgroup_type = "domain";
680
account_ou = gtk_combo_box_get_active_text(GTK_COMBO_BOX(state->entry_ou_list));
681
if (account_ou && strlen(account_ou) == 0) {
685
if ((state->name_type_initial != NetSetupDomainName) &&
686
(state->name_type_new != NetSetupDomainName)) {
687
join_creds_required = FALSE;
688
unjoin_creds_required = FALSE;
691
if (state->name_type_new == NetSetupDomainName) {
693
join_creds_required = TRUE;
694
join_flags = NETSETUP_JOIN_DOMAIN |
695
NETSETUP_ACCT_CREATE |
696
NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
699
if ((state->name_type_initial == NetSetupDomainName) &&
700
(state->name_type_new == NetSetupWorkgroupName)) {
702
unjoin_creds_required = TRUE;
703
join_creds_required = FALSE;
704
unjoin_flags = NETSETUP_JOIN_DOMAIN |
705
NETSETUP_ACCT_DELETE |
706
NETSETUP_IGNORE_UNSUPPORTED_FLAGS;
711
debug("callback_do_join: Unjoining\n");
713
if (unjoin_creds_required) {
714
if (!state->account || !state->password) {
715
debug("callback_do_join: no creds yet\n");
716
callback_creds_prompt(NULL, state,
717
"Enter the name and password of an account with permission to leave the domain.",
718
callback_do_storeauth_and_continue);
721
if (!state->account || !state->password) {
722
debug("callback_do_join: still no creds???\n");
727
status = NetUnjoinDomain(state->target_hostname,
732
callback_do_freeauth(NULL, state);
733
err_str = libnetapi_get_error_string(state->ctx, status);
734
g_print("callback_do_join: failed to unjoin (%s)\n",
738
/* in fact we shouldn't annoy the user with an error message here */
740
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
741
GTK_DIALOG_DESTROY_WITH_PARENT,
744
"The following error occured attempting to unjoin the %s: \"%s\": %s",
745
initial_workgroup_type,
746
state->name_buffer_initial,
748
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
749
gtk_dialog_run(GTK_DIALOG(dialog));
750
gtk_widget_destroy(dialog);
756
/* before prompting for creds, make sure we can find a dc */
760
struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
762
status = DsGetDcName(NULL,
763
state->name_buffer_new,
769
err_str = libnetapi_get_error_string(state->ctx, status);
770
g_print("callback_do_join: failed find dc (%s)\n", err_str);
772
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
773
GTK_DIALOG_DESTROY_WITH_PARENT,
776
"Failed to find a domain controller for domain: \"%s\": %s",
777
state->name_buffer_new,
780
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
781
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
782
g_signal_connect_swapped(dialog, "response",
783
G_CALLBACK(gtk_widget_destroy),
786
gtk_widget_show(dialog);
792
if (join_creds_required) {
793
if (!state->account || !state->password) {
794
debug("callback_do_join: no creds yet\n");
795
callback_creds_prompt(NULL, state,
796
"Enter the name and password of an account with permission to join the domain.",
797
callback_do_storeauth_and_continue);
800
if (!state->account || !state->password) {
801
debug("callback_do_join: still no creds???\n");
806
debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
808
state->name_buffer_new,
811
debug("as %s ", state->account);
812
#ifdef DEBUG_PASSWORD
813
debug("with %s ", state->password);
818
status = NetJoinDomain(state->target_hostname,
819
state->name_buffer_new,
825
callback_do_freeauth(NULL, state);
826
err_str = libnetapi_get_error_string(state->ctx, status);
827
g_print("callback_do_join: failed to join (%s)\n", err_str);
829
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
830
GTK_DIALOG_DESTROY_WITH_PARENT,
833
"The following error occured attempting to join the %s: \"%s\": %s",
835
state->name_buffer_new,
838
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
839
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
840
g_signal_connect_swapped(dialog, "response",
841
G_CALLBACK(gtk_widget_destroy),
844
gtk_widget_show(dialog);
849
debug("callback_do_join: Successfully joined %s\n",
852
callback_do_freeauth(NULL, state);
853
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
854
GTK_DIALOG_DESTROY_WITH_PARENT,
857
"Welcome to the %s %s.",
858
state->name_buffer_new,
861
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
862
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
863
gtk_dialog_run(GTK_DIALOG(dialog));
864
gtk_widget_destroy(dialog);
866
callback_do_reboot(NULL, state->window_parent, state);
869
static void callback_enter_hostname_and_unlock(GtkWidget *widget,
872
const gchar *entry_text = NULL;
874
struct join_state *state = (struct join_state *)data;
876
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
877
debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
878
if (!entry_text || entry_text[0] == 0) {
879
state->hostname_changed = FALSE;
880
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
881
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), "");
884
if (strcasecmp(state->my_hostname, entry_text) == 0) {
885
state->hostname_changed = FALSE;
886
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
889
state->hostname_changed = TRUE;
892
if (state->name_type_initial == NetSetupDomainName) {
893
if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
897
if (asprintf(&str, "%s.", entry_text) == -1) {
901
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
904
if (state->hostname_changed && entry_text && entry_text[0] != 0 && entry_text[0] != '.') {
905
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
909
static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
912
const gchar *entry_text = NULL;
913
struct join_state *state = (struct join_state *)data;
914
int string_unchanged = FALSE;
916
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
917
debug("callback_enter_computer_description_and_unlock: %s\n",
920
if (!entry_text || entry_text[0] == 0) {
921
string_unchanged = 1;
922
gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
927
if (entry_text && state->comment && strcasecmp(state->comment, entry_text) == 0) {
928
string_unchanged = TRUE;
929
gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
934
gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
935
SAFE_FREE(state->comment_new);
936
state->comment_new = strdup(entry_text);
941
static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
944
const gchar *entry_text = NULL;
945
struct join_state *state = (struct join_state *)data;
947
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
948
debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
949
if (!entry_text || entry_text[0] == 0) {
950
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
953
if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
954
(state->name_type_initial == NetSetupWorkgroupName)) {
955
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
958
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
959
SAFE_FREE(state->name_buffer_new);
960
state->name_buffer_new = strdup(entry_text);
961
state->name_type_new = NetSetupWorkgroupName;
964
static void callback_enter_domain_and_unlock(GtkWidget *widget,
967
const gchar *entry_text = NULL;
968
struct join_state *state = (struct join_state *)data;
970
entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
971
debug("callback_enter_domain_and_unlock: %s\n", entry_text);
972
if (!entry_text || entry_text[0] == 0) {
973
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
976
if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
977
(state->name_type_initial == NetSetupDomainName)) {
978
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
981
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
982
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), TRUE);
983
gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), TRUE);
984
SAFE_FREE(state->name_buffer_new);
985
state->name_buffer_new = strdup(entry_text);
986
state->name_type_new = NetSetupDomainName;
989
static void callback_apply_continue(GtkWidget *widget,
992
struct join_state *state = (struct join_state *)data;
994
gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
995
g_signal_emit_by_name(state->button_apply, "clicked");
998
static void callback_do_join_workgroup(GtkWidget *widget,
1001
struct join_state *state = (struct join_state *)data;
1002
debug("callback_do_join_workgroup choosen\n");
1003
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
1004
gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
1005
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
1006
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), FALSE);
1007
gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
1008
callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
1011
static void callback_do_join_domain(GtkWidget *widget,
1014
struct join_state *state = (struct join_state *)data;
1015
debug("callback_do_join_domain choosen\n");
1016
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
1017
gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
1018
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
1019
callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
1022
static void callback_do_getous(GtkWidget *widget,
1025
NET_API_STATUS status;
1026
uint32_t num_ous = 0;
1027
const char **ous = NULL;
1029
const char *domain = NULL;
1030
struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
1031
const char *err_str = NULL;
1034
struct join_state *state = (struct join_state *)data;
1036
debug("callback_do_getous called\n");
1038
domain = state->name_buffer_new ? state->name_buffer_new : state->name_buffer_initial;
1040
status = DsGetDcName(NULL,
1047
err_str = libnetapi_get_error_string(state->ctx, status);
1048
g_print("callback_do_getous: failed find dc (%s)\n", err_str);
1050
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
1051
GTK_DIALOG_DESTROY_WITH_PARENT,
1054
"Failed to find a domain controller for domain: \"%s\": %s",
1058
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1059
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
1060
g_signal_connect_swapped(dialog, "response",
1061
G_CALLBACK(gtk_widget_destroy),
1064
gtk_widget_show(dialog);
1069
if (!state->account || !state->password) {
1070
debug("callback_do_getous: no creds yet\n");
1071
callback_creds_prompt(NULL, state,
1072
"Enter the name and password of an account with permission to join the domain.",
1073
callback_do_storeauth_and_scan);
1076
if (!state->account || !state->password) {
1077
debug("callback_do_getous: still no creds ???\n");
1081
status = NetGetJoinableOUs(state->target_hostname,
1086
if (status != NET_API_STATUS_SUCCESS) {
1087
callback_do_freeauth(NULL, state);
1088
debug("failed to call NetGetJoinableOUs: %s\n",
1089
libnetapi_get_error_string(state->ctx, status));
1090
dialog = gtk_message_dialog_new(NULL,
1091
GTK_DIALOG_DESTROY_WITH_PARENT,
1094
"Failed to query joinable OUs: %s",
1095
libnetapi_get_error_string(state->ctx, status));
1096
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1097
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
1098
gtk_dialog_run(GTK_DIALOG(dialog));
1099
gtk_widget_destroy(dialog);
1103
for (i=0; i<state->stored_num_ous; i++) {
1104
gtk_combo_box_remove_text(GTK_COMBO_BOX(state->entry_ou_list), 0);
1106
for (i=0; i<num_ous && ous[i] != NULL; i++) {
1107
gtk_combo_box_append_text(GTK_COMBO_BOX(state->entry_ou_list),
1110
NetApiBufferFree(ous);
1111
state->stored_num_ous = num_ous;
1112
gtk_combo_box_set_active(GTK_COMBO_BOX(state->entry_ou_list), num_ous-1);
1115
static void callback_do_change(GtkWidget *widget,
1121
GtkWidget *button_workgroup;
1122
GtkWidget *button_domain;
1125
GtkWidget *frame_horz;
1130
struct join_state *state = (struct join_state *)data;
1132
debug("callback_do_change called\n");
1135
/* FIXME: add proper warnings for Samba as a DC */
1136
if (state->server_role == 3) {
1138
callback_do_freeauth(NULL, state);
1139
dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
1140
GTK_DIALOG_DESTROY_WITH_PARENT,
1143
"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.");
1144
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1145
g_signal_connect_swapped(dialog, "response",
1146
G_CALLBACK(gtk_widget_destroy),
1149
gtk_widget_show(dialog);
1154
state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
1155
state->button_get_ous = gtk_button_new_with_label("Scan for joinable OUs");
1156
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1157
gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1159
gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
1160
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1161
gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
1162
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1163
gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_main));
1164
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
1166
g_signal_connect(G_OBJECT(window), "delete_event",
1167
G_CALLBACK(callback_do_close_widget), NULL);
1169
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1171
box1 = gtk_vbox_new(FALSE, 0);
1172
gtk_container_add(GTK_CONTAINER(window), box1);
1174
label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
1175
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1176
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1177
gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1178
gtk_widget_show(label);
1181
label = gtk_label_new("Computer name:");
1182
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1183
gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1184
gtk_widget_show(label);
1186
state->label_full_computer_name = gtk_label_new(NULL);
1188
entry = gtk_entry_new();
1189
gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
1190
g_signal_connect(G_OBJECT(entry), "changed",
1191
G_CALLBACK(callback_enter_hostname_and_unlock),
1193
gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
1194
gtk_editable_select_region(GTK_EDITABLE(entry),
1195
0, GTK_ENTRY(entry)->text_length);
1197
gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1198
gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
1199
gtk_widget_show(entry);
1202
/* FULL COMPUTER NAME */
1203
label = gtk_label_new("Full computer name:");
1204
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1205
gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1206
gtk_widget_show(label);
1209
const gchar *entry_text;
1211
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
1212
if (state->name_type_initial == NetSetupDomainName) {
1213
if (asprintf(&str, "%s.%s", entry_text,
1214
state->my_dnsdomain) == -1) {
1218
if (asprintf(&str, "%s.", entry_text) == -1) {
1222
gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
1225
gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
1226
gtk_box_pack_start(GTK_BOX(box1),
1227
state->label_full_computer_name, TRUE, TRUE, 0);
1228
gtk_widget_show(state->label_full_computer_name);
1232
frame_horz = gtk_frame_new ("Member Of");
1233
gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1235
vbox = gtk_vbox_new(FALSE, 0);
1236
gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1237
gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1240
state->entry_workgroup = gtk_entry_new();
1241
state->entry_domain = gtk_entry_new();
1244
button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
1245
if (state->name_type_initial == NetSetupDomainName) {
1246
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
1248
gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
1249
g_signal_connect(G_OBJECT(button_domain), "clicked",
1250
G_CALLBACK(callback_do_join_domain),
1254
gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
1255
g_signal_connect(G_OBJECT(state->entry_domain), "changed",
1256
G_CALLBACK(callback_enter_domain_and_unlock),
1258
g_signal_connect(G_OBJECT(state->entry_domain), "activate",
1259
G_CALLBACK(callback_continue),
1261
if (state->name_type_initial == NetSetupDomainName) {
1262
gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
1263
state->name_buffer_initial);
1264
gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
1265
gtk_widget_set_sensitive(state->entry_domain, TRUE);
1267
gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
1268
gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
1269
gtk_widget_show(state->entry_domain);
1271
gtk_widget_show(button_domain);
1274
group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
1275
button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
1276
if (state->name_type_initial == NetSetupWorkgroupName) {
1277
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
1279
gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
1280
g_signal_connect(G_OBJECT(button_workgroup), "clicked",
1281
G_CALLBACK(callback_do_join_workgroup),
1284
gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
1285
MAX_NETBIOS_NAME_LEN);
1286
g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
1287
G_CALLBACK(callback_enter_workgroup_and_unlock),
1289
g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
1290
G_CALLBACK(callback_continue),
1293
if (state->name_type_initial == NetSetupWorkgroupName) {
1294
gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
1295
state->name_buffer_initial);
1296
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
1297
gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
1299
gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
1300
gtk_widget_show(state->entry_workgroup);
1302
gtk_widget_show(button_workgroup);
1304
/* Advanced Options */
1305
frame_horz = gtk_frame_new("Advanced Options");
1306
gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1308
vbox = gtk_vbox_new(FALSE, 0);
1309
gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1310
gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1313
gtk_container_add(GTK_CONTAINER(vbox), state->button_get_ous);
1314
gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
1315
g_signal_connect(G_OBJECT(state->button_get_ous), "clicked",
1316
G_CALLBACK(callback_do_getous),
1319
state->entry_ou_list = gtk_combo_box_entry_new_text();
1320
gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1321
if (state->name_type_initial == NetSetupWorkgroupName) {
1322
gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1323
gtk_widget_set_sensitive(state->button_get_ous, FALSE);
1325
gtk_box_pack_start(GTK_BOX(vbox), state->entry_ou_list, TRUE, TRUE, 0);
1326
gtk_widget_show(state->entry_ou_list);
1329
state->label_winbind = gtk_check_button_new_with_label("Modify winbind configuration");
1330
gtk_box_pack_start(GTK_BOX(vbox), state->label_winbind, TRUE, TRUE, 0);
1331
gtk_widget_set_sensitive(state->label_winbind, FALSE);
1336
bbox = gtk_hbutton_box_new();
1337
gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1338
gtk_container_add(GTK_CONTAINER(box1), bbox);
1339
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1340
gtk_box_set_spacing(GTK_BOX(bbox), 10);
1342
state->window_do_change = window;
1343
gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
1344
gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
1345
g_signal_connect(G_OBJECT(state->button_ok), "clicked",
1346
G_CALLBACK(callback_do_join),
1349
button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1350
gtk_container_add(GTK_CONTAINER(bbox), button);
1351
g_signal_connect(G_OBJECT(button), "clicked",
1352
G_CALLBACK(callback_do_freeauth_and_close),
1355
gtk_widget_show_all(window);
1358
static void callback_do_about(GtkWidget *widget,
1362
GError *error = NULL;
1365
struct join_state *state = (struct join_state *)data;
1367
debug("callback_do_about called\n");
1369
logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
1372
g_print("failed to load logo from %s: %s\n",
1373
SAMBA_IMAGE_PATH, error->message);
1376
about = gtk_about_dialog_new();
1377
gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "Samba");
1378
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), "3.2.0pre3");
1379
gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
1380
"Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
1381
"Copyright Günther Deschner 2007-2008");
1382
gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), "GPLv3");
1383
gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1384
gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1386
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo);
1388
gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
1389
gtk_window_set_modal(GTK_WINDOW(about), TRUE);
1390
gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(state->window_main));
1391
g_signal_connect_swapped(about, "response",
1392
G_CALLBACK(gtk_widget_destroy),
1395
gtk_widget_show(about);
1398
static int draw_main_window(struct join_state *state)
1403
GtkWidget *main_vbox;
1411
GError *error = NULL;
1413
icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
1416
g_print("failed to load icon from %s : %s\n",
1417
SAMBA_ICON_PATH, error->message);
1421
image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
1423
image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
1425
if (image == NULL) {
1426
g_print("failed to load logo from %s : %s\n",
1427
SAMBA_IMAGE_PATH_SMALL, error->message);
1430
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1431
state->window_main = window;
1433
gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
1434
gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
1435
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1436
gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1437
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
1439
g_signal_connect(G_OBJECT(window), "delete_event",
1440
G_CALLBACK(callback_delete_event), NULL);
1442
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1444
main_vbox = gtk_vbox_new(FALSE, 10);
1445
gtk_container_add(GTK_CONTAINER(window), main_vbox);
1448
gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
1449
gtk_widget_show(image);
1452
hbox = gtk_hbox_new(FALSE, 10);
1453
gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
1456
/* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
1457
/* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
1458
gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
1459
gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
1460
gtk_widget_show(image);
1463
label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
1464
/* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1465
gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
1466
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1467
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1468
gtk_widget_show(label);
1471
gtk_widget_show(hbox);
1473
vbox = gtk_vbox_new(FALSE, 0);
1474
gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1475
gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
1478
table = gtk_table_new(6, 3, TRUE);
1479
gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1480
gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1481
gtk_container_add(GTK_CONTAINER(vbox), table);
1485
label = gtk_label_new("Computer description:");
1486
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1487
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1488
gtk_widget_show(label);
1490
state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
1493
entry = gtk_entry_new();
1494
gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
1496
if (!state->target_hostname && state->uid != 0) {
1497
gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
1499
g_signal_connect(G_OBJECT(entry), "changed",
1500
G_CALLBACK(callback_enter_computer_description_and_unlock),
1502
g_signal_connect(G_OBJECT(entry), "activate",
1503
G_CALLBACK(callback_apply_continue),
1506
gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
1507
gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1508
gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
1509
gtk_widget_show(entry);
1513
label = gtk_label_new("For example: \"Samba \%v\".");
1514
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1515
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1516
gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
1517
gtk_widget_show(label);
1520
label = gtk_label_new("Full computer name:");
1521
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1522
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
1523
gtk_widget_show(label);
1528
if (state->name_type_initial == NetSetupDomainName) {
1529
if (asprintf(&str, "%s.%s", state->my_hostname,
1530
state->my_dnsdomain) == -1) {
1534
if (asprintf(&str, "%s.", state->my_hostname) == -1) {
1539
label = gtk_label_new(str);
1541
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1542
gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
1543
gtk_widget_show(label);
1547
if (state->name_type_initial == NetSetupDomainName) {
1548
label = gtk_label_new("Domain:");
1550
label = gtk_label_new("Workgroup:");
1552
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1553
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
1554
gtk_widget_show(label);
1555
state->label_current_name_type = label;
1558
label = gtk_label_new(state->name_buffer_initial);
1559
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1560
gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
1561
gtk_widget_show(label);
1562
state->label_current_name_buffer = label;
1565
hbox = gtk_hbox_new(FALSE, 0);
1566
gtk_container_add(GTK_CONTAINER(vbox), hbox);
1567
label = gtk_label_new("To rename this computer or join a domain, click Change.");
1568
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1574
bbox = gtk_hbutton_box_new();
1575
gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1576
gtk_container_add(GTK_CONTAINER(hbox), bbox);
1577
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1578
gtk_box_set_spacing(GTK_BOX(bbox), 10);
1580
button = gtk_button_new_with_mnemonic("Ch_ange");
1581
g_signal_connect(G_OBJECT(button), "clicked",
1582
G_CALLBACK(callback_do_change),
1584
gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
1585
if (!state->target_hostname && state->uid != 0) {
1586
gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
1588
gtk_widget_show(button);
1590
/* Label (hidden) */
1591
state->label_reboot = gtk_label_new(NULL);
1592
gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
1593
gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
1594
gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
1595
if (!state->target_hostname && state->uid != 0) {
1596
gtk_label_set_text(GTK_LABEL(state->label_reboot),
1597
"You cannot change computer description as you're not running with root permissions");
1600
gtk_widget_show(state->label_reboot);
1603
gtk_box_pack_start(GTK_BOX(vbox),
1604
create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
1613
frame = gtk_frame_new(NULL);
1614
bbox2 = gtk_hbutton_box_new();
1616
gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
1617
gtk_container_add(GTK_CONTAINER(frame), bbox2);
1619
/* Set the appearance of the Button Box */
1620
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
1621
gtk_box_set_spacing(GTK_BOX(bbox2), 10);
1622
/*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
1624
button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
1625
gtk_container_add(GTK_CONTAINER(bbox2), button2);
1626
g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
1628
button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1629
gtk_container_add(GTK_CONTAINER(bbox2), button2);
1630
g_signal_connect(G_OBJECT(button2), "clicked",
1631
G_CALLBACK(callback_delete_event),
1634
gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
1635
g_signal_connect(G_OBJECT(state->button_apply), "clicked",
1636
G_CALLBACK(callback_apply_description_change),
1638
gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
1640
button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
1641
gtk_container_add(GTK_CONTAINER(bbox2), button2);
1642
g_signal_connect(G_OBJECT(button2), "clicked",
1643
G_CALLBACK(callback_do_about),
1646
button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
1647
gtk_container_add(GTK_CONTAINER(bbox2), button2);
1648
g_signal_connect(G_OBJECT(button2), "clicked",
1649
G_CALLBACK(callback_do_about),
1652
gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
1655
gtk_widget_show_all(window);
1660
static int init_join_state(struct join_state **state)
1662
struct join_state *s;
1664
s = (struct join_state *)malloc(sizeof(struct join_state));
1669
memset(s, '\0', sizeof(struct join_state));
1676
static NET_API_STATUS get_server_properties(struct join_state *state)
1678
struct SERVER_INFO_101 *info101 = NULL;
1679
struct SERVER_INFO_1005 *info1005 = NULL;
1680
NET_API_STATUS status;
1682
status = NetServerGetInfo(state->target_hostname,
1684
(uint8_t **)&info101);
1686
state->comment = strdup(info101->sv101_comment);
1687
if (!state->comment) {
1690
SAFE_FREE(state->my_hostname);
1691
state->my_hostname = strdup(info101->sv101_name);
1692
if (!state->my_hostname) {
1695
NetApiBufferFree(info101);
1696
return NET_API_STATUS_SUCCESS;
1700
case 124: /* WERR_UNKNOWN_LEVEL */
1701
case 50: /* WERR_NOT_SUPPORTED */
1707
status = NetServerGetInfo(state->target_hostname,
1709
(uint8_t **)&info1005);
1711
state->comment = strdup(info1005->sv1005_comment);
1712
if (!state->comment) {
1715
NetApiBufferFree(info1005);
1716
return NET_API_STATUS_SUCCESS;
1720
printf("NetServerGetInfo failed with: %s\n",
1721
libnetapi_get_error_string(state->ctx, status));
1726
static int initialize_join_state(struct join_state *state,
1727
const char *debug_level,
1728
const char *target_hostname,
1729
const char *target_username)
1731
struct libnetapi_ctx *ctx = NULL;
1732
NET_API_STATUS status = 0;
1734
status = libnetapi_init(&ctx);
1740
libnetapi_set_debuglevel(ctx, debug_level);
1743
if (target_hostname) {
1744
state->target_hostname = strdup(target_hostname);
1745
if (!state->target_hostname) {
1750
if (target_username) {
1751
char *puser = strdup(target_username);
1754
if ((p = strchr(puser,'%'))) {
1757
libnetapi_set_username(ctx, puser);
1758
libnetapi_set_password(ctx, p+1);
1760
memset(strchr(target_username,'%')+1,'X',len);
1762
libnetapi_set_username(ctx, puser);
1768
char my_hostname[HOST_NAME_MAX];
1769
const char *p = NULL;
1770
struct hostent *hp = NULL;
1772
if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1776
p = strchr(my_hostname, '.');
1778
my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
1780
state->my_hostname = strdup(my_hostname);
1781
if (!state->my_hostname) {
1784
debug("state->my_hostname: %s\n", state->my_hostname);
1786
hp = gethostbyname(my_hostname);
1787
if (!hp || !hp->h_name || !*hp->h_name) {
1791
state->my_fqdn = strdup(hp->h_name);
1792
if (!state->my_fqdn) {
1795
debug("state->my_fqdn: %s\n", state->my_fqdn);
1797
p = strchr(state->my_fqdn, '.');
1800
state->my_dnsdomain = strdup(p);
1802
state->my_dnsdomain = strdup("");
1804
if (!state->my_dnsdomain) {
1807
debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
1811
const char *buffer = NULL;
1813
status = NetGetJoinInformation(state->target_hostname,
1817
printf("NetGetJoinInformation failed with: %s\n",
1818
libnetapi_get_error_string(state->ctx, status));
1821
debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
1822
state->name_buffer_initial = strdup(buffer);
1823
if (!state->name_buffer_initial) {
1826
state->name_type_initial = type;
1827
NetApiBufferFree((void *)buffer);
1830
status = get_server_properties(state);
1835
state->uid = geteuid();
1842
int main(int argc, char **argv)
1844
GOptionContext *context = NULL;
1845
static const char *debug_level = NULL;
1846
static const char *target_hostname = NULL;
1847
static const char *target_username = NULL;
1848
struct join_state *state = NULL;
1849
GError *error = NULL;
1852
static GOptionEntry entries[] = {
1853
{ "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
1854
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
1855
{ "target", 'S', 0, G_OPTION_ARG_STRING, &target_hostname, "Target hostname", 0 },
1856
{ "username", 'U', 0, G_OPTION_ARG_STRING, &target_username, "Target hostname", 0 },
1860
context = g_option_context_new("- Samba domain join utility");
1861
g_option_context_add_main_entries(context, entries, NULL);
1862
/* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
1863
g_option_context_add_group(context, gtk_get_option_group(TRUE));
1864
g_option_context_parse(context, &argc, &argv, &error);
1866
gtk_init(&argc, &argv);
1867
g_set_application_name("Samba");
1869
ret = init_join_state(&state);
1874
ret = initialize_join_state(state, debug_level,
1881
draw_main_window(state);