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:
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
149
source3/libads/kerberos.c
Normal 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
352
source3/libads/krb5_setpw.c
Normal 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
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
************************************************************************/
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
143
source3/utils/net_join.c
Normal 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
|
Reference in New Issue
Block a user