2004-10-08 16:31:13 +04:00
/*
Unix SMB / CIFS implementation .
LDAP server
Copyright ( C ) Stefan Metzmacher 2004
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 0213 9 , USA .
*/
# include "includes.h"
2004-11-02 09:52:59 +03:00
# include "ldap_server/ldap_server.h"
2005-01-01 01:45:11 +03:00
# include "auth/auth.h"
2006-01-06 07:01:23 +03:00
# include "libcli/ldap/ldap.h"
2005-06-16 15:36:09 +04:00
# include "smbd/service_stream.h"
2006-01-13 03:38:35 +03:00
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
2005-12-28 18:38:36 +03:00
# include "dsdb/samdb/samdb.h"
2004-10-08 16:31:13 +04:00
2004-10-10 02:00:00 +04:00
static NTSTATUS ldapsrv_BindSimple ( struct ldapsrv_call * call )
2004-10-08 16:31:13 +04:00
{
2005-06-15 04:27:51 +04:00
struct ldap_BindRequest * req = & call - > request - > r . BindRequest ;
2004-10-08 16:31:13 +04:00
struct ldapsrv_reply * reply ;
struct ldap_BindResponse * resp ;
2005-12-19 09:56:45 +03:00
int result ;
const char * errstr ;
const char * nt4_domain , * nt4_account ;
struct auth_session_info * session_info ;
NTSTATUS status ;
2004-10-10 02:00:00 +04:00
DEBUG ( 10 , ( " BindSimple dn: %s \n " , req - > dn ) ) ;
2004-10-08 16:31:13 +04:00
2005-12-19 09:56:45 +03:00
status = crack_dn_to_nt4_name ( call , req - > dn , & nt4_domain , & nt4_account ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
status = authenticate_username_pw ( call , nt4_domain , nt4_account ,
req - > creds . password , & session_info ) ;
}
2005-10-07 15:31:45 +04:00
/* When we add authentication here, we also need to handle telling the backends */
2004-10-08 16:31:13 +04:00
reply = ldapsrv_init_reply ( call , LDAP_TAG_BindResponse ) ;
if ( ! reply ) {
return NT_STATUS_NO_MEMORY ;
}
2005-12-19 09:56:45 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
result = LDAP_SUCCESS ;
errstr = NULL ;
talloc_free ( call - > conn - > session_info ) ;
call - > conn - > session_info = session_info ;
2006-01-13 03:38:35 +03:00
/* don't leak the old LDB */
talloc_free ( call - > conn - > ldb ) ;
status = ldapsrv_backend_Init ( call - > conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
result = LDAP_OPERATIONS_ERROR ;
errstr = talloc_asprintf ( reply , " Simple Bind: Failed to advise ldb new credentials: %s " , nt_errstr ( status ) ) ;
2005-12-19 09:56:45 +03:00
}
} else {
status = auth_nt_status_squash ( status ) ;
result = LDAP_INVALID_CREDENTIALS ;
errstr = talloc_asprintf ( reply , " Simple Bind Failed: %s " , nt_errstr ( status ) ) ;
}
2005-06-15 04:27:51 +04:00
resp = & reply - > msg - > r . BindResponse ;
2005-12-19 09:56:45 +03:00
resp - > response . resultcode = result ;
resp - > response . errormessage = errstr ;
2004-10-08 16:31:13 +04:00
resp - > response . dn = NULL ;
resp - > response . referral = NULL ;
2005-12-19 09:56:45 +03:00
/* This looks wrong... */
2004-10-08 16:31:13 +04:00
resp - > SASL . secblob = data_blob ( NULL , 0 ) ;
2005-06-19 13:31:34 +04:00
ldapsrv_queue_reply ( call , reply ) ;
return NT_STATUS_OK ;
2004-10-08 16:31:13 +04:00
}
2004-10-10 02:00:00 +04:00
static NTSTATUS ldapsrv_BindSASL ( struct ldapsrv_call * call )
{
2005-06-15 04:27:51 +04:00
struct ldap_BindRequest * req = & call - > request - > r . BindRequest ;
2004-10-10 02:00:00 +04:00
struct ldapsrv_reply * reply ;
struct ldap_BindResponse * resp ;
2005-01-01 01:45:11 +03:00
struct ldapsrv_connection * conn ;
2006-02-04 12:48:22 +03:00
int result = 0 ;
2004-10-10 02:00:00 +04:00
const char * errstr ;
NTSTATUS status = NT_STATUS_OK ;
2005-06-14 07:55:27 +04:00
2004-10-10 02:00:00 +04:00
DEBUG ( 10 , ( " BindSASL dn: %s \n " , req - > dn ) ) ;
reply = ldapsrv_init_reply ( call , LDAP_TAG_BindResponse ) ;
if ( ! reply ) {
return NT_STATUS_NO_MEMORY ;
}
2005-06-15 04:27:51 +04:00
resp = & reply - > msg - > r . BindResponse ;
2005-01-01 01:45:11 +03:00
conn = call - > conn ;
2004-10-10 02:00:00 +04:00
2006-02-04 12:48:22 +03:00
if ( ! conn - > gensec ) {
conn - > session_info = NULL ;
status = gensec_server_start ( conn , & conn - > gensec ,
conn - > connection - > event . ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to start GENSEC server code: %s \n " , nt_errstr ( status ) ) ) ;
result = LDAP_OPERATIONS_ERROR ;
errstr = talloc_asprintf ( reply , " SASL: Failed to start authentication system: %s " ,
nt_errstr ( status ) ) ;
} else {
gensec_set_target_service ( conn - > gensec , " ldap " ) ;
gensec_set_credentials ( conn - > gensec , conn - > server_credentials ) ;
gensec_want_feature ( conn - > gensec , GENSEC_FEATURE_SIGN ) ;
gensec_want_feature ( conn - > gensec , GENSEC_FEATURE_SEAL ) ;
gensec_want_feature ( conn - > gensec , GENSEC_FEATURE_ASYNC_REPLIES ) ;
status = gensec_start_mech_by_sasl_name ( conn - > gensec , req - > creds . SASL . mechanism ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to start GENSEC SASL[%s] server code: %s \n " ,
req - > creds . SASL . mechanism , nt_errstr ( status ) ) ) ;
result = LDAP_OPERATIONS_ERROR ;
errstr = talloc_asprintf ( reply , " SASL:[%s]: Failed to start authentication backend: %s " ,
req - > creds . SASL . mechanism , nt_errstr ( status ) ) ;
}
}
}
2004-10-10 02:00:00 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2006-02-04 12:48:22 +03:00
status = gensec_update ( conn - > gensec , reply ,
2005-06-14 07:55:27 +04:00
req - > creds . SASL . secblob , & resp - > SASL . secblob ) ;
2006-02-04 12:48:22 +03:00
} else {
resp - > SASL . secblob = data_blob ( NULL , 0 ) ;
2004-10-10 02:00:00 +04:00
}
if ( NT_STATUS_EQUAL ( NT_STATUS_MORE_PROCESSING_REQUIRED , status ) ) {
result = LDAP_SASL_BIND_IN_PROGRESS ;
errstr = NULL ;
} else if ( NT_STATUS_IS_OK ( status ) ) {
2005-10-08 13:55:38 +04:00
struct auth_session_info * old_session_info ;
2005-10-07 15:31:45 +04:00
2004-10-10 02:00:00 +04:00
result = LDAP_SUCCESS ;
errstr = NULL ;
2006-02-04 12:48:22 +03:00
if ( gensec_have_feature ( conn - > gensec , GENSEC_FEATURE_SEAL ) | |
gensec_have_feature ( conn - > gensec , GENSEC_FEATURE_SIGN ) ) {
conn - > enable_wrap = True ;
2005-06-24 04:03:17 +04:00
}
2006-02-04 12:48:22 +03:00
old_session_info = conn - > session_info ;
conn - > session_info = NULL ;
status = gensec_session_info ( conn - > gensec , & conn - > session_info ) ;
2005-10-07 15:31:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-04 12:48:22 +03:00
conn - > session_info = old_session_info ;
2005-10-07 15:31:45 +04:00
result = LDAP_OPERATIONS_ERROR ;
errstr = talloc_asprintf ( reply , " SASL:[%s]: Failed to get session info: %s " , req - > creds . SASL . mechanism , nt_errstr ( status ) ) ;
} else {
2005-10-08 13:55:38 +04:00
talloc_free ( old_session_info ) ;
2006-01-13 03:38:35 +03:00
/* don't leak the old LDB */
2006-02-04 12:48:22 +03:00
talloc_free ( conn - > ldb ) ;
2006-01-13 03:38:35 +03:00
2006-02-04 12:48:22 +03:00
status = ldapsrv_backend_Init ( conn ) ;
2006-01-13 03:38:35 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
result = LDAP_OPERATIONS_ERROR ;
errstr = talloc_asprintf ( reply , " SASL:[%s]: Failed to advise samdb of new credentials: %s " , req - > creds . SASL . mechanism , nt_errstr ( status ) ) ;
2005-10-07 15:31:45 +04:00
}
}
2004-10-10 02:00:00 +04:00
} else {
2005-10-07 15:31:45 +04:00
status = auth_nt_status_squash ( status ) ;
2006-02-04 12:48:22 +03:00
if ( result = = 0 ) {
result = LDAP_INVALID_CREDENTIALS ;
errstr = talloc_asprintf ( reply , " SASL:[%s]: %s " , req - > creds . SASL . mechanism , nt_errstr ( status ) ) ;
}
2004-10-10 02:00:00 +04:00
}
resp - > response . resultcode = result ;
resp - > response . dn = NULL ;
resp - > response . errormessage = errstr ;
resp - > response . referral = NULL ;
2005-06-19 13:31:34 +04:00
ldapsrv_queue_reply ( call , reply ) ;
return NT_STATUS_OK ;
2004-10-10 02:00:00 +04:00
}
NTSTATUS ldapsrv_BindRequest ( struct ldapsrv_call * call )
{
2005-06-15 04:27:51 +04:00
struct ldap_BindRequest * req = & call - > request - > r . BindRequest ;
2004-10-10 02:00:00 +04:00
struct ldapsrv_reply * reply ;
struct ldap_BindResponse * resp ;
switch ( req - > mechanism ) {
case LDAP_AUTH_MECH_SIMPLE :
return ldapsrv_BindSimple ( call ) ;
case LDAP_AUTH_MECH_SASL :
return ldapsrv_BindSASL ( call ) ;
}
reply = ldapsrv_init_reply ( call , LDAP_TAG_BindResponse ) ;
if ( ! reply ) {
return NT_STATUS_NO_MEMORY ;
}
2005-06-15 04:27:51 +04:00
resp = & reply - > msg - > r . BindResponse ;
2004-10-10 02:00:00 +04:00
resp - > response . resultcode = 7 ;
resp - > response . dn = NULL ;
resp - > response . errormessage = talloc_asprintf ( reply , " Bad AuthenticationChoice [%d] " , req - > mechanism ) ;
resp - > response . referral = NULL ;
resp - > SASL . secblob = data_blob ( NULL , 0 ) ;
2005-06-19 13:31:34 +04:00
ldapsrv_queue_reply ( call , reply ) ;
return NT_STATUS_OK ;
2004-10-10 02:00:00 +04:00
}
2004-10-08 16:31:13 +04:00
NTSTATUS ldapsrv_UnbindRequest ( struct ldapsrv_call * call )
{
DEBUG ( 10 , ( " UnbindRequest \n " ) ) ;
return NT_STATUS_OK ;
}