2004-05-03 14:58:08 +00:00
/*
Unix SMB / CIFS implementation .
interface functions for the sam database
Copyright ( C ) Andrew Tridgell 2004
2006-07-06 05:23:29 +00:00
Copyright ( C ) Volker Lendecke 2004
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2006
2004-05-03 14:58:08 +00:00
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
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2004-05-03 14:58:08 +00:00
( 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-05-03 14:58:08 +00:00
*/
# include "includes.h"
2004-11-02 02:57:18 +00:00
# include "librpc/gen_ndr/ndr_netlogon.h"
2005-07-27 22:14:55 +00:00
# include "librpc/gen_ndr/ndr_misc.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_security.h"
2008-06-14 11:24:17 -04:00
# include "lib/events/events.h"
2004-11-16 09:00:52 +00:00
# include "lib/ldb/include/ldb.h"
2005-12-09 23:39:00 +00:00
# include "lib/ldb/include/ldb_errors.h"
2006-04-02 12:02:01 +00:00
# include "libcli/security/security.h"
2006-11-07 00:48:36 +00:00
# include "libcli/auth/libcli_auth.h"
2007-12-06 21:39:49 +01:00
# include "libcli/ldap/ldap_ndr.h"
2005-01-12 02:40:25 +00:00
# include "system/time.h"
2005-02-10 05:09:35 +00:00
# include "system/filesys.h"
2007-11-16 20:12:00 +01:00
# include "ldb_wrap.h"
# include "util/util_ldb.h"
2005-12-28 15:38:36 +00:00
# include "dsdb/samdb/samdb.h"
2006-08-30 11:29:34 +00:00
# include "dsdb/common/flags.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2008-04-21 19:53:29 -04:00
# include "lib/events/events.h"
2008-07-15 15:07:13 +10:00
# include "auth/credentials/credentials.h"
# include "param/secrets.h"
2004-05-03 14:58:08 +00:00
2007-11-13 22:38:55 +01:00
char * samdb_relative_path ( struct ldb_context * ldb ,
TALLOC_CTX * mem_ctx ,
const char * name )
{
const char * base_url =
( const char * ) ldb_get_opaque ( ldb , " ldb_url " ) ;
char * path , * p , * full_name ;
if ( name = = NULL ) {
return NULL ;
}
if ( name [ 0 ] = = 0 | | name [ 0 ] = = ' / ' | | strstr ( name , " :/ " ) ) {
return talloc_strdup ( mem_ctx , name ) ;
}
path = talloc_strdup ( mem_ctx , base_url ) ;
if ( path = = NULL ) {
return NULL ;
}
if ( ( p = strrchr ( path , ' / ' ) ) ! = NULL ) {
p [ 0 ] = ' \0 ' ;
full_name = talloc_asprintf ( mem_ctx , " %s/%s " , path , name ) ;
} else {
full_name = talloc_asprintf ( mem_ctx , " ./%s " , name ) ;
}
talloc_free ( path ) ;
return full_name ;
}
2008-07-15 15:07:13 +10:00
struct cli_credentials * samdb_credentials ( TALLOC_CTX * mem_ctx ,
struct event_context * event_ctx ,
struct loadparm_context * lp_ctx )
{
struct cli_credentials * cred = cli_credentials_init ( mem_ctx ) ;
if ( ! cred ) {
return NULL ;
}
cli_credentials_set_conf ( cred , lp_ctx ) ;
/* We don't want to use krb5 to talk to our samdb - recursion
* here would be bad , and this account isn ' t in the KDC
* anyway */
cli_credentials_set_kerberos_state ( cred , CRED_DONT_USE_KERBEROS ) ;
if ( ! NT_STATUS_IS_OK ( cli_credentials_set_secrets ( cred , event_ctx , lp_ctx , NULL , NULL ,
SECRETS_LDAP_FILTER ) ) ) {
/* Perfectly OK - if not against an LDAP backend */
return NULL ;
}
return cred ;
}
2007-11-13 22:38:55 +01:00
2004-05-03 14:58:08 +00:00
/*
connect to the SAM database
2004-05-06 12:42:42 +00:00
return an opaque context pointer on success , or NULL on failure
2004-05-03 14:58:08 +00:00
*/
2005-12-14 07:22:25 +00:00
struct ldb_context * samdb_connect ( TALLOC_CTX * mem_ctx ,
2008-04-17 12:23:44 +02:00
struct event_context * ev_ctx ,
2007-12-02 17:09:52 +01:00
struct loadparm_context * lp_ctx ,
2005-12-14 07:22:25 +00:00
struct auth_session_info * session_info )
2004-05-03 14:58:08 +00:00
{
2005-10-07 11:31:45 +00:00
struct ldb_context * ldb ;
2008-04-17 12:23:44 +02:00
ldb = ldb_wrap_connect ( mem_ctx , ev_ctx , lp_ctx ,
2007-12-02 17:09:52 +01:00
lp_sam_url ( lp_ctx ) , session_info ,
2008-07-15 15:07:13 +10:00
samdb_credentials ( mem_ctx , ev_ctx , lp_ctx ) ,
0 , NULL ) ;
2005-12-14 07:22:25 +00:00
if ( ! ldb ) {
2005-10-07 11:31:45 +00:00
return NULL ;
}
2007-06-21 10:18:20 +00:00
dsdb_make_schema_global ( ldb ) ;
2005-10-07 11:31:45 +00:00
return ldb ;
2004-05-06 12:42:42 +00:00
}
2004-05-06 09:55:05 +00:00
2004-12-30 17:01:49 +00:00
/*
2007-12-17 04:22:44 +01:00
copy from a template record to a message
2007-02-22 15:53:06 +00:00
*/
2007-12-17 04:22:44 +01:00
int samdb_copy_template ( struct ldb_context * ldb ,
struct ldb_message * msg , const char * name ,
const char * * errstring )
2007-02-22 15:53:06 +00:00
{
2007-12-17 04:22:44 +01:00
struct ldb_result * res ;
struct ldb_message * t ;
int ret , i , j ;
struct ldb_context * templates_ldb ;
char * templates_ldb_path ;
struct ldb_dn * basedn ;
2008-04-17 12:23:44 +02:00
struct event_context * event_ctx ;
struct loadparm_context * lp_ctx ;
2007-02-22 15:53:06 +00:00
2007-12-17 04:22:44 +01:00
templates_ldb = talloc_get_type ( ldb_get_opaque ( ldb , " templates_ldb " ) , struct ldb_context ) ;
2006-12-13 11:19:51 +00:00
2007-12-17 04:22:44 +01:00
if ( ! templates_ldb ) {
templates_ldb_path = samdb_relative_path ( ldb ,
2008-02-09 14:02:14 +11:00
msg ,
" templates.ldb " ) ;
2007-12-17 04:22:44 +01:00
if ( ! templates_ldb_path ) {
* errstring = talloc_asprintf ( msg , " samdb_copy_template: ERROR: Failed to contruct path for template db " ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2008-04-17 12:23:44 +02:00
2008-06-14 11:24:17 -04:00
event_ctx = ldb_get_event_context ( ldb ) ;
2008-04-17 12:23:44 +02:00
lp_ctx = ( struct loadparm_context * ) ldb_get_opaque ( ldb , " loadparm " ) ;
2006-12-13 11:19:51 +00:00
2008-04-21 19:53:29 -04:00
/* FIXME: need to remove this wehn we finally pass the event
* context around in ldb */
if ( event_ctx = = NULL ) {
2008-06-14 13:00:53 -04:00
event_ctx = s4_event_context_init ( templates_ldb ) ;
2008-04-21 19:53:29 -04:00
}
2008-04-17 12:23:44 +02:00
templates_ldb = ldb_wrap_connect ( ldb , event_ctx , lp_ctx ,
2007-12-17 04:22:44 +01:00
templates_ldb_path , NULL ,
NULL , 0 , NULL ) ;
talloc_free ( templates_ldb_path ) ;
if ( ! templates_ldb ) {
2008-02-09 14:02:14 +11:00
* errstring = talloc_asprintf ( msg , " samdb_copy_template: ERROR: Failed to connect to templates db at: %s " ,
templates_ldb_path ) ;
2007-12-17 04:22:44 +01:00
return LDB_ERR_OPERATIONS_ERROR ;
}
ret = ldb_set_opaque ( ldb , " templates_ldb " , templates_ldb ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2006-12-13 11:19:51 +00:00
}
2007-12-17 04:22:44 +01:00
* errstring = NULL ;
2006-12-13 11:19:51 +00:00
2007-12-17 04:22:44 +01:00
basedn = ldb_dn_new ( templates_ldb , ldb , " cn=Templates " ) ;
if ( ! ldb_dn_add_child_fmt ( basedn , " CN=Template%s " , name ) ) {
talloc_free ( basedn ) ;
* errstring = talloc_asprintf ( msg , " samdb_copy_template: ERROR: Failed to contruct DN for template '%s' " ,
name ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-12-13 11:19:51 +00:00
}
2006-12-22 07:04:06 +00:00
2007-12-17 04:22:44 +01:00
/* pull the template record */
2008-09-23 14:30:06 -04:00
ret = ldb_search ( templates_ldb , msg , & res , basedn , LDB_SCOPE_BASE , NULL , " distinguishedName=* " ) ;
2007-12-17 04:22:44 +01:00
talloc_free ( basedn ) ;
2007-11-13 22:38:55 +01:00
if ( ret ! = LDB_SUCCESS ) {
2007-12-17 04:22:44 +01:00
* errstring = talloc_steal ( msg , ldb_errstring ( templates_ldb ) ) ;
2007-11-13 22:38:55 +01:00
return ret ;
}
if ( res - > count ! = 1 ) {
2007-12-17 04:22:44 +01:00
* errstring = talloc_asprintf ( msg , " samdb_copy_template: ERROR: template '%s' matched %d records, expected 1 " ,
name ,
res - > count ) ;
talloc_free ( res ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2006-03-19 18:06:36 +00:00
}
2007-12-17 04:22:44 +01:00
t = res - > msgs [ 0 ] ;
2006-03-19 18:06:36 +00:00
2007-12-17 04:22:44 +01:00
for ( i = 0 ; i < t - > num_elements ; i + + ) {
struct ldb_message_element * el = & t - > elements [ i ] ;
/* some elements should not be copied from the template */
if ( ldb_attr_cmp ( el - > name , " cn " ) = = 0 | |
ldb_attr_cmp ( el - > name , " name " ) = = 0 | |
ldb_attr_cmp ( el - > name , " objectClass " ) = = 0 | |
ldb_attr_cmp ( el - > name , " sAMAccountName " ) = = 0 | |
ldb_attr_cmp ( el - > name , " sAMAccountName " ) = = 0 | |
ldb_attr_cmp ( el - > name , " distinguishedName " ) = = 0 | |
ldb_attr_cmp ( el - > name , " objectGUID " ) = = 0 ) {
continue ;
2006-03-19 18:06:36 +00:00
}
2007-12-17 04:22:44 +01:00
for ( j = 0 ; j < el - > num_values ; j + + ) {
ret = samdb_find_or_add_attribute ( ldb , msg , el - > name ,
( char * ) el - > values [ j ] . data ) ;
if ( ret ) {
* errstring = talloc_asprintf ( msg , " Adding attribute %s failed. " , el - > name ) ;
talloc_free ( res ) ;
return ret ;
2006-03-19 18:06:36 +00:00
}
}
}
2007-12-17 04:22:44 +01:00
talloc_free ( res ) ;
2006-03-19 18:06:36 +00:00
2007-12-17 04:22:44 +01:00
return LDB_SUCCESS ;
2006-03-19 18:06:36 +00:00
}
2006-04-27 16:09:17 +00:00
/****************************************************************************
Create the SID list for this user .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS security_token_create ( TALLOC_CTX * mem_ctx ,
2008-04-17 12:23:44 +02:00
struct event_context * ev_ctx ,
2007-12-02 19:04:33 +01:00
struct loadparm_context * lp_ctx ,
2006-04-27 16:09:17 +00:00
struct dom_sid * user_sid ,
struct dom_sid * group_sid ,
int n_groupSIDs ,
struct dom_sid * * groupSIDs ,
2007-10-06 22:25:41 +00:00
bool is_authenticated ,
2006-04-27 16:09:17 +00:00
struct security_token * * token )
{
struct security_token * ptoken ;
int i ;
NTSTATUS status ;
ptoken = security_token_initialise ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( ptoken ) ;
ptoken - > sids = talloc_array ( ptoken , struct dom_sid * , n_groupSIDs + 5 ) ;
NT_STATUS_HAVE_NO_MEMORY ( ptoken - > sids ) ;
ptoken - > user_sid = talloc_reference ( ptoken , user_sid ) ;
ptoken - > group_sid = talloc_reference ( ptoken , group_sid ) ;
ptoken - > privilege_mask = 0 ;
ptoken - > sids [ 0 ] = ptoken - > user_sid ;
ptoken - > sids [ 1 ] = ptoken - > group_sid ;
/*
* Finally add the " standard " SIDs .
* The only difference between guest and " anonymous "
* is the addition of Authenticated_Users .
*/
ptoken - > sids [ 2 ] = dom_sid_parse_talloc ( ptoken - > sids , SID_WORLD ) ;
NT_STATUS_HAVE_NO_MEMORY ( ptoken - > sids [ 2 ] ) ;
ptoken - > sids [ 3 ] = dom_sid_parse_talloc ( ptoken - > sids , SID_NT_NETWORK ) ;
NT_STATUS_HAVE_NO_MEMORY ( ptoken - > sids [ 3 ] ) ;
ptoken - > num_sids = 4 ;
if ( is_authenticated ) {
ptoken - > sids [ 4 ] = dom_sid_parse_talloc ( ptoken - > sids , SID_NT_AUTHENTICATED_USERS ) ;
NT_STATUS_HAVE_NO_MEMORY ( ptoken - > sids [ 4 ] ) ;
ptoken - > num_sids + + ;
}
for ( i = 0 ; i < n_groupSIDs ; i + + ) {
size_t check_sid_idx ;
for ( check_sid_idx = 1 ;
check_sid_idx < ptoken - > num_sids ;
check_sid_idx + + ) {
if ( dom_sid_equal ( ptoken - > sids [ check_sid_idx ] , groupSIDs [ i ] ) ) {
break ;
}
}
if ( check_sid_idx = = ptoken - > num_sids ) {
ptoken - > sids [ ptoken - > num_sids + + ] = talloc_reference ( ptoken - > sids , groupSIDs [ i ] ) ;
}
}
/* setup the privilege mask for this token */
2008-04-17 12:23:44 +02:00
status = samdb_privilege_setup ( ev_ctx , lp_ctx , ptoken ) ;
2006-04-27 16:09:17 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( ptoken ) ;
return status ;
}
security_token_debug ( 10 , ptoken ) ;
* token = ptoken ;
return NT_STATUS_OK ;
}