Copyright (C) Stefan Metzmacher 2004
Copyright (C) Simo Sorce 2004
+ Copyright (C) Matthias Dieter Wallnöfer 2009
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "torture/torture.h"
#include "torture/ldap/proto.h"
-static BOOL test_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
+#include "param/param.h"
+
+static bool test_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
{
NTSTATUS status;
- BOOL ret = True;
+ bool ret = true;
status = torture_ldap_bind(conn, userdn, password);
if (!NT_STATUS_IS_OK(status)) {
- ret = False;
+ ret = false;
}
return ret;
}
-static BOOL test_bind_sasl(struct ldap_connection *conn, struct cli_credentials *creds)
+static bool test_bind_sasl(struct torture_context *tctx,
+ struct ldap_connection *conn, struct cli_credentials *creds)
{
NTSTATUS status;
- BOOL ret = True;
+ bool ret = true;
printf("Testing sasl bind as user\n");
- status = torture_ldap_bind_sasl(conn, creds);
+ status = torture_ldap_bind_sasl(conn, creds, tctx->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
- ret = False;
+ ret = false;
}
return ret;
}
-static BOOL test_multibind(struct ldap_connection *conn, const char *userdn, const char *password)
+static bool test_multibind(struct ldap_connection *conn, const char *userdn, const char *password)
{
- BOOL ret = True;
+ bool ret = true;
printf("Testing multiple binds on a single connnection as anonymous and user\n");
return ret;
}
-static BOOL test_search_rootDSE(struct ldap_connection *conn, char **basedn)
+static bool test_search_rootDSE(struct ldap_connection *conn, char **basedn)
{
- BOOL ret = True;
+ bool ret = true;
struct ldap_message *msg, *result;
struct ldap_request *req;
int i;
msg = new_ldap_message(conn);
if (!msg) {
- return False;
+ return false;
}
msg->type = LDAP_TAG_SearchRequest;
msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
msg->r.SearchRequest.timelimit = 0;
msg->r.SearchRequest.sizelimit = 0;
- msg->r.SearchRequest.attributesonly = False;
+ msg->r.SearchRequest.attributesonly = false;
msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
msg->r.SearchRequest.num_attributes = 0;
msg->r.SearchRequest.attributes = NULL;
req = ldap_request_send(conn, msg);
if (req == NULL) {
printf("Could not setup ldap search\n");
- return False;
+ return false;
}
status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
if (!NT_STATUS_IS_OK(status)) {
printf("search failed - %s\n", nt_errstr(status));
- return False;
+ return false;
}
printf("received %d replies\n", req->num_replies);
return ret;
}
-static BOOL test_compare_sasl(struct ldap_connection *conn, const char *basedn)
+static bool test_compare_sasl(struct ldap_connection *conn, const char *basedn)
{
struct ldap_message *msg, *rep;
struct ldap_request *req;
printf("Testing SASL Compare: %s\n", basedn);
if (!basedn) {
- return False;
+ return false;
}
msg = new_ldap_message(conn);
if (!msg) {
- return False;
+ return false;
}
msg->type = LDAP_TAG_CompareRequest;
req = ldap_request_send(conn, msg);
if (!req) {
- return False;
+ return false;
}
status = ldap_result_one(req, &rep, LDAP_TAG_CompareResponse);
if (!NT_STATUS_IS_OK(status)) {
printf("error in ldap compare request - %s\n", nt_errstr(status));
- return False;
+ return false;
}
DEBUG(5,("Code: %d DN: [%s] ERROR:[%s] REFERRAL:[%s]\n",
rep->r.CompareResponse.errormessage,
rep->r.CompareResponse.referral));
- return True;
+ return true;
}
+/*
+ * This takes an AD error message and splits it into the WERROR code
+ * (WERR_DS_GENERIC if none found) and the reason (remaining string).
+ */
+static WERROR ad_error(const char *err_msg, char **reason)
+{
+ WERROR err = W_ERROR(strtol(err_msg, reason, 16));
+
+ if ((reason != NULL) && (*reason[0] != ':')) {
+ return WERR_DS_GENERIC_ERROR; /* not an AD std error message */
+ }
+
+ if (reason != NULL) {
+ *reason += 2; /* skip ": " */
+ }
+ return err;
+}
+
+static bool test_error_codes(struct torture_context *tctx,
+ struct ldap_connection *conn, const char *basedn)
+{
+ struct ldap_message *msg, *rep;
+ struct ldap_request *req;
+ char *err_code_str, *endptr;
+ WERROR err;
+ NTSTATUS status;
+
+ printf("Testing error codes\n");
+
+ if (!basedn) {
+ return false;
+ }
+
+ msg = new_ldap_message(conn);
+ if (!msg) {
+ return false;
+ }
+
+ printf(" Try a wrong addition\n");
+
+ msg->type = LDAP_TAG_AddRequest;
+ msg->r.AddRequest.dn = basedn;
+ msg->r.AddRequest.num_attributes = 0;
+ msg->r.AddRequest.attributes = NULL;
+
+ req = ldap_request_send(conn, msg);
+ if (!req) {
+ return false;
+ }
+
+ status = ldap_result_one(req, &rep, LDAP_TAG_AddResponse);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("error in ldap addition request - %s\n", nt_errstr(status));
+ return false;
+ }
+
+ if ((rep->r.AddResponse.resultcode == 0)
+ || (rep->r.AddResponse.errormessage == NULL)
+ || (strtol(rep->r.AddResponse.errormessage, &endptr,16) <= 0)
+ || (*endptr != ':')) {
+ printf("Invalid error message!\n");
+ return false;
+ }
+
+ err = ad_error(rep->r.AddResponse.errormessage, &endptr);
+ err_code_str = win_errstr(err);
+ printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
+ if (torture_setting_bool(tctx, "samba4", false)) {
+ if ((!W_ERROR_EQUAL(err, WERR_DS_REFERRAL))
+ || (rep->r.AddResponse.resultcode != 10)) {
+ return false;
+ }
+ } else {
+ if ((!W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
+ || (rep->r.AddResponse.resultcode != 80)) {
+ return false;
+ }
+ }
+
+ printf(" Try a wrong modification\n");
+
+ msg->type = LDAP_TAG_ModifyRequest;
+ msg->r.ModifyRequest.dn = "";
+ msg->r.ModifyRequest.num_mods = 0;
+ msg->r.ModifyRequest.mods = NULL;
+
+ req = ldap_request_send(conn, msg);
+ if (!req) {
+ return false;
+ }
+
+ status = ldap_result_one(req, &rep, LDAP_TAG_ModifyResponse);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("error in ldap modifification request - %s\n", nt_errstr(status));
+ return false;
+ }
+
+ if ((rep->r.ModifyResponse.resultcode == 0)
+ || (rep->r.ModifyResponse.errormessage == NULL)
+ || (strtol(rep->r.ModifyResponse.errormessage, &endptr,16) <= 0)
+ || (*endptr != ':')) {
+ printf("Invalid error message!\n");
+ return false;
+ }
-BOOL torture_ldap_basic(struct torture_context *torture)
+ err = ad_error(rep->r.ModifyResponse.errormessage, &endptr);
+ err_code_str = win_errstr(err);
+ printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
+ if (torture_setting_bool(tctx, "samba4", false)) {
+ if ((!W_ERROR_EQUAL(err, WERR_INVALID_PARAM))
+ || (rep->r.ModifyResponse.resultcode != 53)) {
+ return false;
+ }
+ } else {
+ if ((!W_ERROR_EQUAL(err, WERR_DS_GENERIC_ERROR))
+ || (rep->r.ModifyResponse.resultcode != 80)) {
+ return false;
+ }
+ }
+
+ printf(" Try a wrong removal\n");
+
+ msg->type = LDAP_TAG_DelRequest;
+ msg->r.DelRequest.dn = "";
+
+ req = ldap_request_send(conn, msg);
+ if (!req) {
+ return false;
+ }
+
+ status = ldap_result_one(req, &rep, LDAP_TAG_DelResponse);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("error in ldap removal request - %s\n", nt_errstr(status));
+ return false;
+ }
+
+ if ((rep->r.DelResponse.resultcode == 0)
+ || (rep->r.DelResponse.errormessage == NULL)
+ || (strtol(rep->r.DelResponse.errormessage, &endptr,16) <= 0)
+ || (*endptr != ':')) {
+ printf("Invalid error message!\n");
+ return false;
+ }
+
+ err = ad_error(rep->r.DelResponse.errormessage, &endptr);
+ err_code_str = win_errstr(err);
+ printf(" - Errorcode: %s; Reason: %s\n", err_code_str, endptr);
+ if (torture_setting_bool(tctx, "samba4", false)) {
+ if ((!W_ERROR_EQUAL(err, WERR_DS_OBJ_NOT_FOUND))
+ || (rep->r.DelResponse.resultcode != 32)) {
+ return false;
+ }
+ } else {
+ if ((!W_ERROR_EQUAL(err, WERR_DS_INVALID_DN_SYNTAX))
+ || (rep->r.DelResponse.resultcode != 34)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool torture_ldap_basic(struct torture_context *torture)
{
NTSTATUS status;
struct ldap_connection *conn;
TALLOC_CTX *mem_ctx;
- BOOL ret = True;
+ bool ret = true;
const char *host = torture_setting_string(torture, "host", NULL);
const char *userdn = torture_setting_string(torture, "ldap_userdn", NULL);
const char *secret = torture_setting_string(torture, "ldap_secret", NULL);
url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
- status = torture_ldap_connection(mem_ctx, &conn, url);
+ status = torture_ldap_connection(torture, &conn, url);
if (!NT_STATUS_IS_OK(status)) {
- return False;
+ return false;
}
if (!test_search_rootDSE(conn, &basedn)) {
- ret = False;
+ ret = false;
}
- /* other basic tests here */
+ /* other bind tests here */
if (!test_multibind(conn, userdn, secret)) {
- ret = False;
+ ret = false;
}
- if (!test_bind_sasl(conn, cmdline_credentials)) {
- ret = False;
+ if (!test_bind_sasl(torture, conn, cmdline_credentials)) {
+ ret = false;
}
if (!test_compare_sasl(conn, basedn)) {
- ret = False;
+ ret = false;
}
- /* no more test we are closing */
- torture_ldap_close(conn);
- talloc_free(mem_ctx);
+ /* error codes test here */
+
+ if (!test_error_codes(torture, conn, basedn)) {
+ ret = false;
+ }
+ /* if there are no more tests we are closing */
+ torture_ldap_close(conn);
+ talloc_free(mem_ctx);
return ret;
}