1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-03 04:22:09 +03:00

added "net join" command

this completes the first stage of the smbd ADS support
(This used to be commit 058a5aee90)
This commit is contained in:
Andrew Tridgell
2001-11-24 14:16:41 +00:00
parent 0ebb29e032
commit ad2974cd05
19 changed files with 903 additions and 252 deletions

View File

@ -115,6 +115,23 @@ Here are some other suggestions:
comment start / ** so that they can be picked up by Doxygen, as in
this file.
23) Keep the scope narrow. This means making functions/variables
static whenever possible. We don't want our namespace
polluted. Each module should have a minimal number of externally
visible functions or variables.
24) Use function pointers to keep knowledge about particular pieces of
code isolated in one place. We don't want a particular piece of
functionality to be spread out across lots of places - that makes
for fragile, hand to maintain code. Instead, design an interface
and use tables containing function pointers to implement specific
functionality. This is particularly important for command
interpreters.
25) Think carefully about what it will be like for someone else to add
to and maintain your code. If it would be hard for someone else to
maintain then do it another way.
The suggestions above are simply that, suggestions, but the information may
help in reducing the routine rework done on new code. The preceeding list
is expected to change routinely as new support routines and macros are

View File

@ -131,7 +131,7 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
PARAM_OBJ = param/loadparm.o param/params.o dynconfig.o
LIBADS_OBJ = libads/ldap.o
LIBADS_OBJ = libads/ldap.o libads/krb5_setpw.o libads/kerberos.o passdb/secrets.o
LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clikrb5.o libsmb/clispnego.o libsmb/asn1.o \
@ -179,7 +179,7 @@ RPC_CLIENT_OBJ = rpc_client/cli_netlogon.o rpc_client/cli_pipe.o \
LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
PASSDB_OBJ = passdb/passdb.o passdb/secrets.o \
PASSDB_OBJ = passdb/passdb.o \
passdb/machine_sid.o passdb/pdb_smbpasswd.o \
passdb/pdb_tdb.o passdb/pdb_ldap.o \
passdb/pdb_nisplus.o
@ -319,8 +319,8 @@ CLIENT_OBJ = client/client.o client/clitar.o \
$(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
$(READLINE_OBJ)
NET_OBJ = utils/net.o $(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
@BUILD_POPT@
NET_OBJ = utils/net.o utils/net_join.o \
$(LIBSMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) @BUILD_POPT@
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ)
@ -375,7 +375,7 @@ SMBFILTER_OBJ = utils/smbfilter.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
PROTO_OBJ = $(SMBD_OBJ) $(NMBD_OBJ) $(SWAT_OBJ) $(CLIENT_OBJ) \
$(SMBWRAPPER_OBJ) $(SMBTORTURE_OBJ) $(RPCCLIENT_OBJ1) \
$(LIBMSRPC_OBJ) $(RPC_CLIENT_OBJ) $(AUTH_OBJ)
$(LIBMSRPC_OBJ) $(RPC_CLIENT_OBJ) $(AUTH_OBJ) $(NET_OBJ)
NSS_OBJ_0 = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ)
NSS_OBJ = $(NSS_OBJ_0:.o=.po)

View File

@ -2159,7 +2159,7 @@ struct cli_state *do_connect(const char *server, const char *share)
password, strlen(password),
workgroup)) {
/* if a password was not supplied then try again with a null username */
if (password[0] || !username[0] ||
if (password[0] || !username[0] || use_kerberos ||
!cli_session_setup(c, "", "", 0, "", 0, workgroup)) {
d_printf("session setup failed: %s\n", cli_errstr(c));
cli_shutdown(c);

View File

@ -233,7 +233,7 @@ add a privilege to a privilege array
****************************************************************************/
BOOL add_privilege(uint32 *privilege, uint32 priv)
{
int i;
int i=0;
while (i<PRIV_ALL_INDEX && privilege[i]!=0 && privilege[i]!=priv)
i++;
@ -262,6 +262,7 @@ BOOL add_all_privilege(uint32 *privilege)
add_privilege(privilege, SE_PRIV_ADD_USERS);
add_privilege(privilege, SE_PRIV_ADD_MACHINES);
add_privilege(privilege, SE_PRIV_PRINT_OPERATOR);
return True;
}
/****************************************************************************
@ -301,7 +302,6 @@ BOOL default_group_mapping(void)
fstring str_admins;
fstring str_users;
fstring str_guests;
int i;
uint32 privilege_none[PRIV_ALL_INDEX];
uint32 privilege_all[PRIV_ALL_INDEX];

View File

@ -737,6 +737,13 @@ typedef struct smb_wpasswd {
wpstring pw_shell;
} SMB_STRUCT_WPASSWD;
/* used in net.c */
struct functable {
char *funcname;
int (*fn)();
};
/* Defines for wisXXX functions. */
#define UNI_UPPER 0x1
#define UNI_LOWER 0x2

View File

@ -22,7 +22,13 @@
#ifndef _SECRETS_H
#define _SECRETS_H
/* the first one is for the hashed password (NT4 style) the latter
for plaintext (ADS
*/
#define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC"
#define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD"
#define SECRETS_DOMAIN_SID "SECRETS/SID"
#define SECRETS_SAM_SID "SAM/SID"

View File

@ -905,6 +905,37 @@ connect_again:
return res;
}
/*
open a connected UDP socket to host on port
*/
int open_udp_socket(const char *host, int port)
{
int type = SOCK_DGRAM;
struct sockaddr_in sock_out;
int res;
struct in_addr *addr;
addr = interpret_addr2(host);
res = socket(PF_INET, type, 0);
if (res == -1) {
return -1;
}
memset((char *)&sock_out,'\0',sizeof(sock_out));
putip((char *)&sock_out.sin_addr,(char *)addr);
sock_out.sin_port = htons(port);
sock_out.sin_family = PF_INET;
if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
close(res);
return -1;
}
return res;
}
/* the following 3 client_*() functions are nasty ways of allowing
some generic functions to get info that really should be hidden in
particular modules */

149
source3/libads/kerberos.c Normal file
View File

@ -0,0 +1,149 @@
/*
Unix SMB/Netbios implementation.
Version 3.0
kerberos utility library
Copyright (C) Andrew Tridgell 2001
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#ifdef HAVE_KRB5
/*
verify an incoming ticket and parse out the principal name and
authorization_data if available
*/
NTSTATUS ads_verify_ticket(const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data)
{
krb5_context context;
krb5_auth_context auth_context = NULL;
krb5_keytab keytab = NULL;
krb5_data packet;
krb5_ticket *tkt = NULL;
krb5_data salt;
krb5_encrypt_block eblock;
int ret;
krb5_keyblock * key;
krb5_principal host_princ;
char *host_princ_s;
extern pstring global_myname;
fstring myname;
char *password_s;
krb5_data password;
if (!secrets_init()) {
DEBUG(1,("secrets_init failed\n"));
return NT_STATUS_LOGON_FAILURE;
}
password_s = secrets_fetch_machine_password();
if (!password_s) {
DEBUG(1,("failed to fetch machine password\n"));
return NT_STATUS_LOGON_FAILURE;
}
password.data = password_s;
password.length = strlen(password_s);
ret = krb5_init_context(&context);
if (ret) {
DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
ret = krb5_set_default_realm(context, lp_realm());
if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
/* this whole process is far more complex than I would
like. We have to go through all this to allow us to store
the secret internally, instead of using /etc/krb5.keytab */
ret = krb5_auth_con_init(context, &auth_context);
if (ret) {
DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
fstrcpy(myname, global_myname);
strlower(myname);
asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
ret = krb5_parse_name(context, host_princ_s, &host_princ);
if (ret) {
DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
ret = krb5_principal2salt(context, host_princ, &salt);
if (ret) {
DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
return NT_STATUS_NO_MEMORY;
}
krb5_use_enctype(context, &eblock, ENCTYPE_DES_CBC_MD5);
ret = krb5_string_to_key(context, &eblock, key, &password, &salt);
if (ret) {
DEBUG(1,("krb5_string_to_key failed (%s)\n", error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
krb5_auth_con_setuseruserkey(context, auth_context, key);
packet.length = ticket->length;
packet.data = (krb5_pointer)ticket->data;
#if 0
file_save("/tmp/ticket.dat", ticket->data, ticket->length);
#endif
if ((ret = krb5_rd_req(context, &auth_context, &packet,
NULL, keytab, NULL, &tkt))) {
DEBUG(3,("krb5_rd_req with auth failed (%s)\n",
error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
if (tkt->enc_part2) {
*auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length);
}
#if 0
if (tkt->enc_part2) {
file_save("/tmp/authdata.dat",
tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length);
}
#endif
if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, principal))) {
DEBUG(3,("krb5_unparse_name failed (%s)\n",
error_message(ret)));
return NT_STATUS_LOGON_FAILURE;
}
return NT_STATUS_OK;
}
#endif

352
source3/libads/krb5_setpw.c Normal file
View File

@ -0,0 +1,352 @@
/*
Unix SMB/Netbios implementation.
Version 3.0
krb5 set password implementation
Copyright (C) Andrew Tridgell 2001
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#if HAVE_KRB5
#define DEFAULT_KPASSWD_PORT 464
#define KRB5_KPASSWD_VERS_CHANGEPW 1
#define KRB5_KPASSWD_VERS_SETPW 0xff80
#define KRB5_KPASSWD_ACCESSDENIED 5
#define KRB5_KPASSWD_BAD_VERSION 6
/* This implements the Kerb password change protocol as specifed in
* kerb-chg-password-02.txt
*/
static DATA_BLOB encode_krb5_setpw(const char *hostname,
const char *realm, const char *password)
{
ASN1_DATA req;
DATA_BLOB ret;
memset(&req, 0, sizeof(req));
asn1_push_tag(&req, ASN1_SEQUENCE(0));
asn1_push_tag(&req, ASN1_CONTEXT(0));
asn1_write_OctetString(&req, password, strlen(password));
asn1_pop_tag(&req);
asn1_push_tag(&req, ASN1_CONTEXT(1));
asn1_push_tag(&req, ASN1_SEQUENCE(0));
asn1_push_tag(&req, ASN1_CONTEXT(0));
asn1_write_Integer(&req, 1);
asn1_pop_tag(&req);
asn1_push_tag(&req, ASN1_CONTEXT(1));
asn1_push_tag(&req, ASN1_SEQUENCE(0));
asn1_write_GeneralString(&req, "HOST");
asn1_write_GeneralString(&req, hostname);
asn1_pop_tag(&req);
asn1_pop_tag(&req);
asn1_pop_tag(&req);
asn1_pop_tag(&req);
asn1_push_tag(&req, ASN1_CONTEXT(2));
asn1_write_GeneralString(&req, realm);
asn1_pop_tag(&req);
asn1_pop_tag(&req);
ret = data_blob(req.data, req.length);
asn1_free(&req);
return ret;
}
static krb5_error_code build_setpw_request(krb5_context context,
krb5_auth_context auth_context,
krb5_data *ap_req,
const char *hostname,
const char *realm,
const char *passwd,
krb5_data *packet)
{
krb5_error_code ret;
krb5_data cipherpw;
krb5_data encoded_setpw;
krb5_replay_data replay;
char *p;
DATA_BLOB setpw;
ret = krb5_auth_con_setflags(context,
auth_context,KRB5_AUTH_CONTEXT_DO_SEQUENCE);
if (ret) {
DEBUG(1,("krb5_auth_con_setflags failed (%s)\n",
error_message(ret)));
return ret;
}
setpw = encode_krb5_setpw(hostname, realm, passwd);
encoded_setpw.data = setpw.data;
encoded_setpw.length = setpw.length;
ret = krb5_mk_priv(context, auth_context,
&encoded_setpw, &cipherpw, &replay);
if (ret) {
DEBUG(1,("krb5_mk_priv failed (%s)\n", error_message(ret)));
return ret;
}
packet->data = (char *)malloc(ap_req->length + cipherpw.length + 6);
/* see the RFC for details */
p = packet->data + 2;
RSSVAL(p, 0, 0xff80); p += 2;
RSSVAL(p, 0, ap_req->length); p += 2;
memcpy(p, ap_req->data, ap_req->length); p += ap_req->length;
memcpy(p, cipherpw.data, cipherpw.length); p += cipherpw.length;
packet->length = PTR_DIFF(p,packet->data);
RSSVAL(packet->data, 0, packet->length);
return 0;
}
static krb5_error_code parse_setpw_reply(krb5_context context,
krb5_auth_context auth_context,
krb5_data *packet)
{
krb5_data ap_rep;
char *p;
int vnum, ret, res_code;
krb5_data cipherresult;
krb5_data clearresult;
krb5_ap_rep_enc_part *ap_rep_enc;
krb5_replay_data replay;
if (packet->length < 4) {
return KRB5KRB_AP_ERR_MODIFIED;
}
p = packet->data;
if (packet->data[0] == 0x7e || packet->data[0] == 0x5e) {
/* it's an error packet. We should parse it ... */
DEBUG(1,("Got error packet 0x%x from kpasswd server\n",
packet->data[0]));
return KRB5KRB_AP_ERR_MODIFIED;
}
if (RSVAL(p, 0) != packet->length) {
DEBUG(1,("Bad packet length (%d/%d) from kpasswd server\n",
RSVAL(p, 0), packet->length));
return KRB5KRB_AP_ERR_MODIFIED;
}
p += 2;
vnum = RSVAL(p, 0); p += 2;
if (vnum != KRB5_KPASSWD_VERS_SETPW && vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
DEBUG(1,("Bad vnum (%d) from kpasswd server\n", vnum));
return KRB5KDC_ERR_BAD_PVNO;
}
ap_rep.length = RSVAL(p, 0); p += 2;
if (p + ap_rep.length >= packet->data + packet->length) {
DEBUG(1,("ptr beyond end of packet from kpasswd server\n"));
return KRB5KRB_AP_ERR_MODIFIED;
}
if (ap_rep.length == 0) {
DEBUG(1,("got unencrypted setpw result?!\n"));
return KRB5KRB_AP_ERR_MODIFIED;
}
/* verify ap_rep */
ap_rep.data = p;
p += ap_rep.length;
ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
if (ret) {
DEBUG(1,("failed to rd setpw reply (%s)\n", error_message(ret)));
return KRB5KRB_AP_ERR_MODIFIED;
}
krb5_free_ap_rep_enc_part(context, ap_rep_enc);
cipherresult.data = p;
cipherresult.length = (packet->data + packet->length) - p;
ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
&replay);
if (ret) {
DEBUG(1,("failed to decrypt setpw reply (%s)\n", error_message(ret)));
return KRB5KRB_AP_ERR_MODIFIED;
}
if (clearresult.length < 2) {
ret = KRB5KRB_AP_ERR_MODIFIED;
return KRB5KRB_AP_ERR_MODIFIED;
}
p = clearresult.data;
res_code = RSVAL(p, 0);
if ((res_code < KRB5_KPASSWD_SUCCESS) ||
(res_code > KRB5_KPASSWD_ACCESSDENIED)) {
return KRB5KRB_AP_ERR_MODIFIED;
}
return 0;
}
NTSTATUS krb5_set_password(const char *kdc_host, const char *hostname,
const char *realm, const char *newpw)
{
krb5_context context;
krb5_auth_context auth_context = NULL;
krb5_principal principal;
char *princ_name;
krb5_creds creds, *credsp;
krb5_ccache ccache;
krb5_data ap_req, chpw_req, chpw_rep;
int ret, sock, addr_len;
struct sockaddr remote_addr, local_addr;
krb5_address local_kaddr, remote_kaddr;
ret = krb5_init_context(&context);
if (ret) {
DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
ret = krb5_cc_default(context, &ccache);
if (ret) {
DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
ZERO_STRUCT(creds);
asprintf(&princ_name, "kadmin/changepw@%s", realm);
ret = krb5_parse_name(context, princ_name, &creds.server);
if (ret) {
DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
free(princ_name);
asprintf(&princ_name, "HOST/%s@%s", hostname, realm);
ret = krb5_parse_name(context, princ_name, &principal);
if (ret) {
DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
free(princ_name);
krb5_princ_set_realm(context, creds.server,
krb5_princ_realm(context, principal));
ret = krb5_cc_get_principal(context, ccache, &creds.client);
if (ret) {
DEBUG(1,("Failed to get principal from ccache (%s)\n",
error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
if (ret) {
DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
NULL, credsp, &ap_req);
if (ret) {
DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
sock = open_udp_socket(kdc_host, DEFAULT_KPASSWD_PORT);
if (sock == -1) {
DEBUG(1,("failed to open kpasswd socket to %s (%s)\n",
kdc_host, strerror(errno)));
return NT_STATUS_UNSUCCESSFUL;
}
addr_len = sizeof(remote_addr);
getpeername(sock, &remote_addr, &addr_len);
addr_len = sizeof(local_addr);
getsockname(sock, &local_addr, &addr_len);
remote_kaddr.addrtype = ADDRTYPE_INET;
remote_kaddr.length = sizeof(((struct sockaddr_in *)&remote_addr)->sin_addr);
remote_kaddr.contents = (char *)&(((struct sockaddr_in *)&remote_addr)->sin_addr);
local_kaddr.addrtype = ADDRTYPE_INET;
local_kaddr.length = sizeof(((struct sockaddr_in *)&local_addr)->sin_addr);
local_kaddr.contents = (char *)&(((struct sockaddr_in *)&local_addr)->sin_addr);
ret = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL);
if (ret) {
DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
ret = build_setpw_request(context, auth_context, &ap_req,
hostname, realm, newpw, &chpw_req);
if (ret) {
DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
if (write(sock, chpw_req.data, chpw_req.length) != chpw_req.length) {
DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
return NT_STATUS_UNSUCCESSFUL;
}
free(chpw_req.data);
chpw_rep.length = 1500;
chpw_rep.data = (char *) malloc(chpw_rep.length);
ret = read(sock, chpw_rep.data, chpw_rep.length);
if (ret < 0) {
DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno)));
return NT_STATUS_UNSUCCESSFUL;
}
close(sock);
chpw_rep.length = ret;
ret = krb5_auth_con_setaddrs(context, auth_context, NULL,&remote_kaddr);
if (ret) {
DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n",
error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
ret = parse_setpw_reply(context, auth_context, &chpw_rep);
free(chpw_rep.data);
if (ret) {
DEBUG(1,("parse_setpw_reply failed (%s)\n",
error_message(ret)));
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_OK;
}
#endif

View File

@ -44,7 +44,7 @@ static char *ads_build_dn(const char *realm)
len = (numdots+1)*4 + strlen(r) + 1;
ret = malloc(len);
ret = malloc(len);
strlcpy(ret,"dc=", len);
p=strtok(r,".");
strlcat(ret, p, len);
@ -67,6 +67,25 @@ char *ads_errstr(int rc)
return ldap_err2string(rc);
}
/*
find the ldap server from DNS
this won't work till we add a DNS packet parser. Talk about a
lousy resolv interface!
*/
static char *find_ldap_server(ADS_STRUCT *ads)
{
char *list = NULL;
if (ldap_domain2hostlist(ads->realm, &list) == LDAP_SUCCESS) {
char *p;
p = strchr(list, ':');
if (p) *p = 0;
return list;
}
return NULL;
}
/*
initialise a ADS_STRUCT, ready for some ads_ ops
*/
@ -76,7 +95,8 @@ ADS_STRUCT *ads_init(const char *realm,
{
ADS_STRUCT *ads;
ads = (ADS_STRUCT *)xmalloc(sizeof(*ads));
ads = (ADS_STRUCT *)malloc(sizeof(*ads));
if (!ads) return NULL;
memset(ads, 0, sizeof(*ads));
ads->realm = realm? strdup(realm) : NULL;
@ -84,17 +104,42 @@ ADS_STRUCT *ads_init(const char *realm,
ads->bind_path = bind_path? strdup(bind_path) : NULL;
ads->ldap_port = LDAP_PORT;
if (!ads->realm) {
ads->realm = lp_realm();
}
if (!ads->bind_path) {
ads->bind_path = ads_build_dn(ads->realm);
}
if (!ads->ldap_server) {
ads->ldap_server = find_ldap_server(ads);
}
if (!ads->kdc_server) {
/* assume its the same as LDAP */
ads->kdc_server = ads->ldap_server? strdup(ads->ldap_server) : NULL;
}
return ads;
}
/*
free the memory used by the ADS structure initialized with 'ads_init(...)'
*/
void ads_destroy(ADS_STRUCT *ads)
{
if (ads->ld) ldap_unbind(ads->ld);
SAFE_FREE(ads->realm);
SAFE_FREE(ads->ldap_server);
SAFE_FREE(ads->kdc_server);
SAFE_FREE(ads->bind_path);
ZERO_STRUCTP(ads);
free(ads);
}
/*
this is a minimal interact function, just enough for SASL to talk
GSSAPI/kerberos to W2K
Error handling is a bit of a problem. I can't see how to get Cyrus-sasl
to give sensible errors
*/
static int sasl_interact(LDAP *ld,unsigned flags,void *defaults,void *in)
{
@ -102,7 +147,7 @@ static int sasl_interact(LDAP *ld,unsigned flags,void *defaults,void *in)
while (interact->id != SASL_CB_LIST_END) {
interact->result = strdup("");
interact->len = 0;
interact->len = strlen(interact->result);
interact++;
}
@ -123,7 +168,8 @@ int ads_connect(ADS_STRUCT *ads)
}
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL, 0,
rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL,
LDAP_SASL_QUIET,
sasl_interact, NULL);
return rc;
@ -290,12 +336,11 @@ int ads_join_realm(ADS_STRUCT *ads, const char *hostname)
{
int rc;
LDAPMessage *res;
char *principal;
rc = ads_find_machine_acct(ads, (void **)&res, hostname);
if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1) {
DEBUG(0, ("Host account for %s already exists\n", hostname));
goto set_password;
return LDAP_SUCCESS;
}
rc = ads_add_machine_acct(ads, hostname);
@ -311,14 +356,48 @@ int ads_join_realm(ADS_STRUCT *ads, const char *hostname)
return -1;
}
set_password:
asprintf(&principal, "HOST/%s@%s", hostname, ads->realm);
#if 0
krb5_set_principal_password(principal, ads->ldap_server, hostname, ads->realm);
#endif
free(principal);
return LDAP_SUCCESS;
}
/*
delete a machine from the realm
*/
int ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
{
int rc;
void *res;
char *hostnameDN;
rc = ads_find_machine_acct(ads, &res, hostname);
if (rc != LDAP_SUCCESS || ads_count_replies(ads, res) != 1) {
DEBUG(0, ("Host account for %s does not exist.\n", hostname));
return -1;
}
hostnameDN = ldap_get_dn(ads->ld, (LDAPMessage *)res);
rc = ldap_delete_s(ads->ld, hostnameDN);
ldap_memfree(hostnameDN);
if (rc != LDAP_SUCCESS) {
DEBUG(0, ("ldap_delete_s: %s\n", ads_errstr(rc)));
return rc;
}
rc = ads_find_machine_acct(ads, &res, hostname);
if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1 ) {
DEBUG(0, ("Failed to remove host account.\n"));
/*hmmm, we need NTSTATUS */
return -1;
}
return LDAP_SUCCESS;
}
NTSTATUS ads_set_machine_password(ADS_STRUCT *ads,
const char *hostname,
const char *password)
{
return krb5_set_password(ads->kdc_server, hostname, ads->realm, password);
}
#endif

View File

@ -95,6 +95,7 @@ DATA_BLOB krb5_get_ticket(char *principal)
krb5_context context;
krb5_auth_context auth_context = NULL;
DATA_BLOB ret;
krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL};
retval = krb5_init_context(&context);
if (retval) {
@ -109,6 +110,12 @@ DATA_BLOB krb5_get_ticket(char *principal)
goto failed;
}
if ((retval = krb5_set_default_tgs_ktypes(context, enc_types))) {
DEBUG(1,("krb5_set_default_tgs_ktypes failed (%s)\n",
error_message(retval)));
goto failed;
}
if ((retval = krb5_mk_req2(context,
&auth_context,
0,

View File

@ -114,6 +114,7 @@ typedef struct
char *szSocketOptions;
char *szWorkGroup;
char *szRealm;
char *szADSserver;
char **szDomainAdminGroup;
char **szDomainGuestGroup;
char *szUsernameMap;
@ -650,6 +651,7 @@ static struct parm_struct parm_table[] = {
{"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, 0},
{"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL, NULL, FLAG_BASIC},
{"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC},
{"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC},
{"netbios name", P_UGSTRING, P_GLOBAL, global_myname, handle_netbios_name, NULL, FLAG_BASIC},
{"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, 0},
{"netbios scope", P_UGSTRING, P_GLOBAL, global_scope, NULL, NULL, 0},
@ -1459,6 +1461,7 @@ FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
FN_GLOBAL_STRING(lp_workgroup, &Globals.szWorkGroup)
FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
#ifdef USING_GROUPNAME_MAP
FN_GLOBAL_STRING(lp_groupname_map, &Globals.szGroupnameMap)

View File

@ -1,8 +1,7 @@
/*
Unix SMB/Netbios implementation.
Version 3.0.
Samba registry functions
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Andrew Tridgell 1992-2001
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -53,7 +52,7 @@ void *secrets_fetch(char *key, size_t *size)
{
TDB_DATA kbuf, dbuf;
if (!tdb)
return False;
return NULL;
kbuf.dptr = key;
kbuf.dsize = strlen(key);
dbuf = tdb_fetch(tdb, kbuf);
@ -142,8 +141,18 @@ BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16],
time_t *pass_last_set_time)
{
struct machine_acct_pass *pass;
char *plaintext;
size_t size;
plaintext = secrets_fetch_machine_password();
if (plaintext) {
/* we have an ADS password - use that */
DEBUG(4,("Using ADS machine password\n"));
E_md4hash((uchar *)plaintext, ret_pwd);
SAFE_FREE(plaintext);
return True;
}
if (!(pass = secrets_fetch(trust_keystr(domain), &size)) ||
size != sizeof(*pass))
return False;
@ -168,6 +177,27 @@ BOOL secrets_store_trust_account_password(char *domain, uint8 new_pwd[16])
return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass));
}
/************************************************************************
Routine to set the plaintext machine account password for a realm
the password is assumed to be a null terminated ascii string
************************************************************************/
BOOL secrets_store_machine_password(char *pass)
{
return secrets_store(SECRETS_MACHINE_PASSWORD, pass, strlen(pass)+1);
}
/************************************************************************
Routine to fetch the plaintext machine account password for a realm
the password is assumed to be a null terminated ascii string
************************************************************************/
char *secrets_fetch_machine_password(void)
{
return (char *)secrets_fetch(SECRETS_MACHINE_PASSWORD, NULL);
}
/************************************************************************
Routine to delete the trust account password file for a domain.
************************************************************************/

View File

@ -2464,8 +2464,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
{
pstring key;
NT_PRINTER_INFO_LEVEL_2 info;
int len = 0,
devmode_length = 0;
int len = 0;
TDB_DATA kbuf, dbuf;
fstring printername;

View File

@ -426,8 +426,6 @@ static NTSTATUS cmd_lsa_lookupprivvalue(struct cli_state *cli,
{
POLICY_HND pol;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
DOM_SID sid;
LUID luid;
if (argc != 2 ) {

View File

@ -122,7 +122,7 @@ END {
gotstart = 1;
}
if( $0 ~ /^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) {
if( $0 ~ /^ADS_STRUCT|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) {
gotstart = 1;
}

View File

@ -73,16 +73,12 @@ static int reply_spnego_kerberos(connection_struct *conn,
DATA_BLOB *secblob)
{
DATA_BLOB ticket;
krb5_context context;
krb5_auth_context auth_context = NULL;
krb5_keytab keytab = NULL;
krb5_data packet;
krb5_ticket *tkt = NULL;
int ret;
char *realm, *client, *p;
const struct passwd *pw;
char *user;
int sess_vuid;
NTSTATUS ret;
DATA_BLOB auth_data;
auth_serversupplied_info *server_info = NULL;
realm = lp_realm();
@ -91,38 +87,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
ret = krb5_init_context(&context);
if (ret) {
DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret)));
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
packet.length = ticket.length;
packet.data = (krb5_pointer)ticket.data;
#if 0
file_save("/tmp/ticket.dat", ticket.data, ticket.length);
#endif
if ((ret = krb5_rd_req(context, &auth_context, &packet,
NULL, keytab, NULL, &tkt))) {
DEBUG(3,("krb5_rd_req failed (%s)\n",
error_message(ret)));
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
#if 0
if (tkt->enc_part2) {
file_save("/tmp/authdata.dat",
tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length);
}
#endif
if ((ret = krb5_unparse_name(context, tkt->enc_part2->client,
&client))) {
DEBUG(3,("krb5_unparse_name failed (%s)\n",
error_message(ret)));
ret = ads_verify_ticket(&ticket, &client, &auth_data);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(1,("Failed to verify incoming ticket!\n"));
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}

View File

@ -37,11 +37,6 @@
#include <includes.h>
struct functable {
char *funcname;
int (*fn)();
};
/***********************************************************************/
/* Beginning of internationalization section. Translatable constants */
/* should be kept in this area and referenced in the rest of the code. */
@ -315,7 +310,7 @@ static struct in_addr dest_ip;
run a function from a function table. If not found then
call the specified usage function
*/
static int run_function(int argc, const char **argv, struct functable *table,
int net_run_function(int argc, const char **argv, struct functable *table,
int (*usage_fn)(void))
{
int i;
@ -506,16 +501,9 @@ static BOOL make_ipc_connection(unsigned flags)
return True;
}
static int net_usage(void)
{
d_printf(NET_USAGE);
return -1;
}
static int file_usage(void)
static int general_usage(void)
{
d_printf(NET_FILE_USAGE); /* command syntax */
d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
@ -530,6 +518,20 @@ static int file_usage(void)
return -1;
}
static int net_usage(void)
{
d_printf(NET_USAGE);
return -1;
}
static int file_usage(void)
{
d_printf(NET_FILE_USAGE); /* command syntax */
general_usage();
return -1;
}
@ -594,26 +596,13 @@ static int net_file(int argc, const char **argv)
return cli_NetFileEnum(cli, NULL, NULL, file_fn);
}
return run_function(argc, argv, func, file_usage);
return net_run_function(argc, argv, func, file_usage);
}
static int share_usage(void)
{
d_printf(NET_SHARE_USAGE); /* command syntax */
d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(COMMENT_USAGE);
d_printf(MAXUSERS_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -686,7 +675,7 @@ static int net_share(int argc, const char **argv)
return cli_RNetShareEnum(cli, share_fn, NULL);
}
return run_function(argc, argv, func, share_usage);
return net_run_function(argc, argv, func, share_usage);
}
@ -694,17 +683,7 @@ static int session_usage(void)
{
d_printf(NET_SESSION_USAGE); /* command syntax */
d_printf(TARGET_USAGE, LOCAL_HOST); /* Target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE); /* Misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -781,7 +760,7 @@ static int net_session(int argc, const char **argv)
return cli_NetSessionEnum(cli, list_sessions_func);
}
return run_function(argc, argv, func, session_usage);
return net_run_function(argc, argv, func, session_usage);
}
/****************************************************************************
@ -797,18 +776,7 @@ static int server_usage(void)
{
d_printf(NET_SERVER_USAGE); /* command syntax */
d_printf(TARGET_USAGE, DOMAIN_MASTER); /* Target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(MISC_OPT_USAGE); /* Misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -823,17 +791,7 @@ static int domain_usage(void)
{
d_printf(NET_DOMAIN_USAGE); /* command syntax */
d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -849,18 +807,7 @@ static int printq_usage(void)
{
d_printf(NET_PRINTQ_USAGE);
d_printf(TARGET_USAGE, LOCAL_HOST);
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE);
d_printf(PORT_USAGE);
d_printf(JOBID_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -949,7 +896,7 @@ static int net_printq(int argc, const char **argv)
return cli_NetPrintQEnum(cli, enum_queue, enum_jobs);
}
return run_function(argc, argv, func, printq_usage);
return net_run_function(argc, argv, func, printq_usage);
}
@ -957,20 +904,7 @@ static int user_usage(void)
{
d_printf(NET_USER_USAGE); /* command syntax */
d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(COMMENT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
d_printf(LONG_USAGE);
general_usage();
return -1;
}
@ -1047,7 +981,7 @@ int net_user(int argc, const char **argv)
return cli_RNetUserEnum(cli, user_fn, NULL);
}
return run_function(argc, argv, func, user_usage);
return net_run_function(argc, argv, func, user_usage);
}
@ -1055,20 +989,7 @@ static int group_usage(void)
{
d_printf(NET_GROUP_USAGE); /* command syntax */
d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(COMMENT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(CONF_USAGE);
d_printf(LONG_USAGE);
general_usage();
return -1;
}
@ -1122,25 +1043,14 @@ static int net_group(int argc, const char **argv)
return cli_RNetGroupEnum(cli, group_fn, NULL);
}
return run_function(argc, argv, func, group_usage);
return net_run_function(argc, argv, func, group_usage);
}
static int groupmember_usage(void)
{
d_printf(NET_GROUPMEMBER_USAGE); /* command syntax */
d_printf(TARGET_USAGE, LOCAL_HOST); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -1181,25 +1091,14 @@ static int net_groupmember(int argc, const char **argv)
{NULL, NULL}
};
return run_function(argc, argv, func, groupmember_usage);
return net_run_function(argc, argv, func, groupmember_usage);
}
static int validate_usage(void)
{
d_printf(NET_VALIDATE_USAGE); /* command syntax */
d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -1213,17 +1112,7 @@ static int service_usage(void)
{
d_printf(NET_SERVICE_USAGE); /* command syntax */
d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -1257,25 +1146,14 @@ static int net_service(int argc, const char **argv)
return cli_RNetServiceEnum(cli, group_fn, NULL);
}
return run_function(argc, argv, func, service_usage);
return net_run_function(argc, argv, func, service_usage);
}
static int password_usage(void)
{
d_printf(NET_PASSWORD_USAGE); /* command syntax */
d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -1294,18 +1172,7 @@ static int admin_usage(void)
{
d_printf(NET_ADMIN_USAGE); /* command syntax */
d_printf(TARGET_USAGE, GLBL_LCL_MASTER); /* target options */
d_printf(SERVER_USAGE);
d_printf(IPADDRESS_USAGE);
d_printf(WORKGROUP_USAGE);
d_printf(MISC_OPT_USAGE); /* misc options */
d_printf(PORT_USAGE);
d_printf(MYWORKGROUP_USAGE);
d_printf(DEBUG_USAGE);
d_printf(MYNAME_USAGE);
d_printf(USER_USAGE);
d_printf(CONF_USAGE);
general_usage();
return -1;
}
@ -1316,18 +1183,6 @@ static int net_admin(int argc, const char **argv)
return 0;
}
static int join_usage(void)
{
d_printf(ERRMSG_NOT_IMPLEMENTED);
return -1;
}
static int net_join(int argc, const char **argv)
{
d_printf(ERRMSG_NOT_IMPLEMENTED);
return 0;
}
static int help_usage(void)
{
d_printf("\n"\
@ -1358,10 +1213,10 @@ static int net_help(int argc, const char **argv)
{"ADMIN", admin_usage},
{"SERVICE", service_usage},
{"PASSWORD", password_usage},
{"JOIN", join_usage},
{"JOIN", net_join_usage},
{NULL, NULL}};
return run_function(argc, argv, func, help_usage);
return net_run_function(argc, argv, func, help_usage);
};
/* main function table */
@ -1397,6 +1252,7 @@ int main(int argc,char *argv[])
const char ** argv_new;
poptContext pc;
char *servicesf = dyn_CONFIGFILE;
extern pstring global_myname;
struct poptOption long_options[] = {
{"help", 'h', POPT_ARG_NONE, 0, 'h'},
@ -1480,9 +1336,16 @@ int main(int argc,char *argv[])
opt_workgroup = lp_workgroup();
}
if (!*global_myname) {
char *p;
fstrcpy(global_myname, myhostname());
p = strchr_m(global_myname, '.');
if (p) *p = 0;
}
load_interfaces();
rc = run_function(argc_new-1, argv_new+1, net_func, net_usage);
rc = net_run_function(argc_new-1, argv_new+1, net_func, net_usage);
DEBUG(2,("return code = %d\n", rc));
return rc;

143
source3/utils/net_join.c Normal file
View File

@ -0,0 +1,143 @@
/*
Samba Unix/Linux SMB client library
Version 3.0
join a realm
Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#if HAVE_ADS
/* a lame random number generator - used /dev/urandom if possible */
static unsigned one_random(void)
{
int fd = -1;
static int initialised;
unsigned ret;
if (!initialised) {
initialised = 1;
fd = open("/dev/urandom", O_RDONLY);
srandom(time(NULL) ^ getpid());
}
if (fd == -1) {
return random();
}
read(fd, &ret, sizeof(ret));
return ret;
}
/*
* Generate a simple random password of 15 chars - not a cryptographic one
*/
static char *generate_random_password(int len)
{
int i;
char *pass;
if (!(pass = malloc(len+1)))
return NULL;
for (i=0; i<len; ) {
char c = one_random() & 0x7f;
if (!isalnum(c) && !ispunct(c)) continue;
pass[i++] = c;
}
return pass;
}
int net_join_usage(void)
{
d_printf("\nnet join"\
"\n\tjoins the local machine to a ADS realm\n");
return -1;
}
int net_join(int argc, const char **argv)
{
char *ldap_host;
char *hostname;
char *realm;
ADS_STRUCT *ads;
int rc;
char *password;
extern pstring global_myname;
NTSTATUS status;
hostname = strdup(global_myname);
strlower(hostname);
realm = lp_realm();
ldap_host = lp_ads_server();
if (!*ldap_host) ldap_host = NULL;
if (!*realm) realm = NULL;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
return -1;
}
password = generate_random_password(15);
ads = ads_init(realm, ldap_host, NULL);
rc = ads_connect(ads);
if (rc) {
d_printf("ads_connect: %s\n", ads_errstr(rc));
return -1;
}
rc = ads_join_realm(ads, hostname);
if (rc) {
d_printf("ads_join_realm: %s\n", ads_errstr(rc));
return -1;
}
status = ads_set_machine_password(ads, hostname, password);
if (!NT_STATUS_IS_OK(status)) {
d_printf("ads_set_machine_password: %s\n", get_nt_error_msg(status));
return -1;
}
if (!secrets_store_machine_password(password)) {
DEBUG(1,("Failed to save machine password\n"));
return -1;
}
d_printf("Joined %s to realm %s\n", hostname, realm);
return 0;
}
#else
int net_join_usage(void)
{
d_printf("ADS support not compiled in\n");
return -1;
}
int net_join(int argc, const char **argv)
{
return net_join_usage();
}
#endif