*/
#include "includes.h"
+#include "system/iconv.h"
+#include "system/filesys.h"
+#include "asn_1.h"
/****************************************************************************
*
if (val && strchr("()&|", *val))
return NULL;
- ret = talloc(mem_ctx, sizeof(*ret));
+ ret = talloc(mem_ctx, struct ldap_parse_tree);
if (!ret) {
errno = ENOMEM;
return NULL;
{
struct ldap_parse_tree *ret, *next;
- ret = talloc(mem_ctx, sizeof(*ret));
-
+ ret = talloc(mem_ctx, struct ldap_parse_tree);
if (!ret) {
errno = ENOMEM;
return NULL;
ret->operation = op;
ret->u.list.num_elements = 1;
- ret->u.list.elements = talloc(mem_ctx, sizeof(*ret->u.list.elements));
+ ret->u.list.elements = talloc(mem_ctx, struct ldap_parse_tree *);
if (!ret->u.list.elements) {
errno = ENOMEM;
return NULL;
while (*s && (next = ldap_parse_filter(mem_ctx, &s))) {
struct ldap_parse_tree **e;
- e = talloc_realloc_p(ret,
+ e = talloc_realloc(ret,
ret->u.list.elements,
struct ldap_parse_tree *,
ret->u.list.num_elements+1);
{
struct ldap_parse_tree *ret;
- ret = talloc(mem_ctx, sizeof(*ret));
+ ret = talloc(mem_ctx, struct ldap_parse_tree);
if (!ret) {
errno = ENOMEM;
return NULL;
return ldap_parse_simple(mem_ctx, s);
}
-static BOOL ldap_push_filter(ASN1_DATA *data, struct ldap_parse_tree *tree)
+static BOOL ldap_push_filter(struct asn1_data *data, struct ldap_parse_tree *tree)
{
switch (tree->operation) {
case LDAP_OP_SIMPLE: {
return !data->has_error;
}
-static void ldap_encode_response(enum ldap_request_tag tag,
- struct ldap_Result *result,
- ASN1_DATA *data)
+static void ldap_encode_response(struct asn1_data *data, struct ldap_Result *result)
{
- asn1_push_tag(data, ASN1_APPLICATION(tag));
asn1_write_enumerated(data, result->resultcode);
asn1_write_OctetString(data, result->dn,
(result->dn) ? strlen(result->dn) : 0);
asn1_write_OctetString(data, result->errormessage,
(result->errormessage) ?
strlen(result->errormessage) : 0);
- if (result->referral != NULL)
+ if (result->referral) {
+ asn1_push_tag(data, ASN1_CONTEXT(3));
asn1_write_OctetString(data, result->referral,
strlen(result->referral));
- asn1_pop_tag(data);
+ asn1_pop_tag(data);
+ }
}
BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
{
- ASN1_DATA data;
+ struct asn1_data data;
int i, j;
ZERO_STRUCT(data);
switch (msg->type) {
case LDAP_TAG_BindRequest: {
struct ldap_BindRequest *r = &msg->r.BindRequest;
- asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_Integer(&data, r->version);
asn1_write_OctetString(&data, r->dn,
(r->dn != NULL) ? strlen(r->dn) : 0);
switch (r->mechanism) {
case LDAP_AUTH_MECH_SIMPLE:
/* context, primitive */
- asn1_push_tag(&data, r->mechanism | 0x80);
+ asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
asn1_write(&data, r->creds.password,
strlen(r->creds.password));
asn1_pop_tag(&data);
break;
case LDAP_AUTH_MECH_SASL:
/* context, constructed */
- asn1_push_tag(&data, r->mechanism | 0xa0);
+ asn1_push_tag(&data, ASN1_CONTEXT(3));
asn1_write_OctetString(&data, r->creds.SASL.mechanism,
strlen(r->creds.SASL.mechanism));
asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
}
case LDAP_TAG_BindResponse: {
struct ldap_BindResponse *r = &msg->r.BindResponse;
- ldap_encode_response(msg->type, &r->response, &data);
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, &r->response);
+ if (r->SASL.secblob.length > 0) {
+ asn1_write_ContextSimple(&data, 7, &r->SASL.secblob);
+ }
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_UnbindRequest: {
}
case LDAP_TAG_SearchRequest: {
struct ldap_SearchRequest *r = &msg->r.SearchRequest;
- asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_OctetString(&data, r->basedn, strlen(r->basedn));
asn1_write_enumerated(&data, r->scope);
asn1_write_enumerated(&data, r->deref);
ldap_push_filter(&data, tree);
- talloc_destroy(mem_ctx);
+ talloc_free(mem_ctx);
}
asn1_push_tag(&data, ASN1_SEQUENCE(0));
}
case LDAP_TAG_SearchResultEntry: {
struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
- asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_OctetString(&data, r->dn, strlen(r->dn));
asn1_push_tag(&data, ASN1_SEQUENCE(0));
for (i=0; i<r->num_attributes; i++) {
}
case LDAP_TAG_SearchResultDone: {
struct ldap_Result *r = &msg->r.SearchResultDone;
- ldap_encode_response(msg->type, r, &data);
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, r);
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_ModifyRequest: {
struct ldap_ModifyRequest *r = &msg->r.ModifyRequest;
- asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ModifyRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_OctetString(&data, r->dn, strlen(r->dn));
asn1_push_tag(&data, ASN1_SEQUENCE(0));
}
case LDAP_TAG_ModifyResponse: {
struct ldap_Result *r = &msg->r.ModifyResponse;
- ldap_encode_response(msg->type, r, &data);
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, r);
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_AddRequest: {
struct ldap_AddRequest *r = &msg->r.AddRequest;
- asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_OctetString(&data, r->dn, strlen(r->dn));
asn1_push_tag(&data, ASN1_SEQUENCE(0));
}
case LDAP_TAG_AddResponse: {
struct ldap_Result *r = &msg->r.AddResponse;
- ldap_encode_response(msg->type, r, &data);
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, r);
+ asn1_pop_tag(&data);
break;
}
- case LDAP_TAG_DeleteRequest: {
- struct ldap_DeleteRequest *r = &msg->r.DeleteRequest;
- asn1_push_tag(&data,
- ASN1_APPLICATION_SIMPLE(LDAP_TAG_DeleteRequest));
+ case LDAP_TAG_DelRequest: {
+ struct ldap_DelRequest *r = &msg->r.DelRequest;
+ asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
asn1_write(&data, r->dn, strlen(r->dn));
asn1_pop_tag(&data);
break;
}
- case LDAP_TAG_DeleteResponse: {
- struct ldap_Result *r = &msg->r.DeleteResponse;
- ldap_encode_response(msg->type, r, &data);
+ case LDAP_TAG_DelResponse: {
+ struct ldap_Result *r = &msg->r.DelResponse;
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, r);
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_ModifyDNRequest: {
struct ldap_ModifyDNRequest *r = &msg->r.ModifyDNRequest;
- asn1_push_tag(&data,
- ASN1_APPLICATION(LDAP_TAG_ModifyDNRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_OctetString(&data, r->dn, strlen(r->dn));
asn1_write_OctetString(&data, r->newrdn, strlen(r->newrdn));
asn1_write_BOOLEAN(&data, r->deleteolddn);
}
case LDAP_TAG_ModifyDNResponse: {
struct ldap_Result *r = &msg->r.ModifyDNResponse;
- ldap_encode_response(msg->type, r, &data);
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, r);
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_CompareRequest: {
struct ldap_CompareRequest *r = &msg->r.CompareRequest;
- asn1_push_tag(&data,
- ASN1_APPLICATION(LDAP_TAG_CompareRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_write_OctetString(&data, r->dn, strlen(r->dn));
asn1_push_tag(&data, ASN1_SEQUENCE(0));
asn1_write_OctetString(&data, r->attribute,
strlen(r->attribute));
- asn1_write_OctetString(&data, r->value,
- strlen(r->value));
+ asn1_write_OctetString(&data, r->value.data,
+ r->value.length);
asn1_pop_tag(&data);
asn1_pop_tag(&data);
break;
}
case LDAP_TAG_CompareResponse: {
-/* struct ldap_Result *r = &msg->r.CompareResponse; */
+ struct ldap_Result *r = &msg->r.ModifyDNResponse;
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, r);
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_AbandonRequest: {
struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
- asn1_push_tag(&data,
- ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION_SIMPLE(msg->type));
asn1_write_implicit_Integer(&data, r->messageid);
asn1_pop_tag(&data);
break;
}
case LDAP_TAG_SearchResultReference: {
-/* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
+ struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ asn1_write_OctetString(&data, r->referral, strlen(r->referral));
+ asn1_pop_tag(&data);
break;
}
case LDAP_TAG_ExtendedRequest: {
struct ldap_ExtendedRequest *r = &msg->r.ExtendedRequest;
- asn1_push_tag(&data, ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
asn1_push_tag(&data, ASN1_CONTEXT_SIMPLE(0));
asn1_write(&data, r->oid, strlen(r->oid));
asn1_pop_tag(&data);
}
case LDAP_TAG_ExtendedResponse: {
struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
- ldap_encode_response(msg->type, &r->response, &data);
+ asn1_push_tag(&data, ASN1_APPLICATION(msg->type));
+ ldap_encode_response(&data, &r->response);
+ asn1_pop_tag(&data);
break;
}
default:
static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,
DATA_BLOB blob)
{
- char *result = talloc(mem_ctx, blob.length+1);
+ char *result = talloc_size(mem_ctx, blob.length+1);
memcpy(result, blob.data, blob.length);
result[blob.length] = '\0';
return result;
}
static BOOL asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,
- ASN1_DATA *data,
+ struct asn1_data *data,
const char **result)
{
DATA_BLOB string;
}
static void ldap_decode_response(TALLOC_CTX *mem_ctx,
- ASN1_DATA *data,
- enum ldap_request_tag tag,
+ struct asn1_data *data,
struct ldap_Result *result)
{
- asn1_start_tag(data, ASN1_APPLICATION(tag));
asn1_read_enumerated(data, &result->resultcode);
asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);
asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);
} else {
result->referral = NULL;
}
- asn1_end_tag(data);
}
-static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
+static BOOL ldap_decode_filter(TALLOC_CTX *mem_ctx, struct asn1_data *data,
char **filter)
{
- uint8 filter_tag, tag_desc;
+ uint8_t filter_tag, tag_desc;
if (!asn1_peek_uint8(data, &filter_tag))
return False;
return True;
}
-static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
+static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,
struct ldap_attribute *attrib)
{
asn1_start_tag(data, ASN1_SEQUENCE(0));
}
-static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, ASN1_DATA *data,
+static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,
struct ldap_attribute **attributes,
int *num_attributes)
{
asn1_end_tag(data);
}
-BOOL ldap_decode(ASN1_DATA *data, struct ldap_message *msg)
+BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
{
- uint8 tag;
+ uint8_t tag;
asn1_start_tag(data, ASN1_SEQUENCE(0));
asn1_read_Integer(data, &msg->messageid);
case ASN1_APPLICATION(LDAP_TAG_BindRequest): {
struct ldap_BindRequest *r = &msg->r.BindRequest;
msg->type = LDAP_TAG_BindRequest;
- asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindRequest));
+ asn1_start_tag(data, tag);
asn1_read_Integer(data, &r->version);
asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
- if (asn1_peek_tag(data, 0x80)) {
+ if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(0))) {
int pwlen;
r->creds.password = "";
- /* Mechanism 0 (SIMPLE) */
- asn1_start_tag(data, 0x80);
+ r->mechanism = LDAP_AUTH_MECH_SIMPLE;
+ asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
pwlen = asn1_tag_remaining(data);
if (pwlen != 0) {
- char *pw = talloc(msg->mem_ctx, pwlen+1);
+ char *pw = talloc_size(msg->mem_ctx, pwlen+1);
asn1_read(data, pw, pwlen);
pw[pwlen] = '\0';
r->creds.password = pw;
}
asn1_end_tag(data);
+ } else if (asn1_peek_tag(data, ASN1_CONTEXT(3))){
+ asn1_start_tag(data, ASN1_CONTEXT(3));
+ r->mechanism = LDAP_AUTH_MECH_SASL;
+ asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->creds.SASL.mechanism);
+ asn1_read_OctetString(data, &r->creds.SASL.secblob);
+ if (r->creds.SASL.secblob.data) {
+ talloc_steal(msg->mem_ctx, r->creds.SASL.secblob.data);
+ }
+ asn1_end_tag(data);
}
asn1_end_tag(data);
break;
case ASN1_APPLICATION(LDAP_TAG_BindResponse): {
struct ldap_BindResponse *r = &msg->r.BindResponse;
msg->type = LDAP_TAG_BindResponse;
- asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_BindResponse));
- asn1_read_enumerated(data, &r->response.resultcode);
- asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.dn);
- asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.errormessage);
- if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
- asn1_start_tag(data, ASN1_CONTEXT(3));
- asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->response.referral);
- asn1_end_tag(data);
- } else {
- r->response.referral = NULL;
- }
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, &r->response);
if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(7))) {
DATA_BLOB tmp_blob = data_blob(NULL, 0);
asn1_read_ContextSimple(data, 7, &tmp_blob);
case ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest): {
msg->type = LDAP_TAG_UnbindRequest;
- asn1_start_tag(data, ASN1_APPLICATION_SIMPLE(LDAP_TAG_UnbindRequest));
+ asn1_start_tag(data, tag);
asn1_end_tag(data);
break;
}
case ASN1_APPLICATION(LDAP_TAG_SearchRequest): {
struct ldap_SearchRequest *r = &msg->r.SearchRequest;
msg->type = LDAP_TAG_SearchRequest;
- asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_SearchRequest));
+ asn1_start_tag(data, tag);
asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->basedn);
asn1_read_enumerated(data, (int *)&(r->scope));
asn1_read_enumerated(data, (int *)&(r->deref));
msg->type = LDAP_TAG_SearchResultEntry;
r->attributes = NULL;
r->num_attributes = 0;
- asn1_start_tag(data,
- ASN1_APPLICATION(LDAP_TAG_SearchResultEntry));
+ asn1_start_tag(data, tag);
asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
ldap_decode_attribs(msg->mem_ctx, data, &r->attributes,
&r->num_attributes);
case ASN1_APPLICATION(LDAP_TAG_SearchResultDone): {
struct ldap_Result *r = &msg->r.SearchResultDone;
msg->type = LDAP_TAG_SearchResultDone;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_SearchResultDone, r);
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, r);
+ asn1_end_tag(data);
break;
}
case ASN1_APPLICATION(LDAP_TAG_SearchResultReference): {
-/* struct ldap_SearchResRef *r = &msg->r.SearchResultReference; */
+ struct ldap_SearchResRef *r = &msg->r.SearchResultReference;
msg->type = LDAP_TAG_SearchResultReference;
+ asn1_start_tag(data, tag);
+ asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->referral);
+ asn1_end_tag(data);
break;
}
while (asn1_tag_remaining(data) > 0) {
struct ldap_mod mod;
+ int v;
ZERO_STRUCT(mod);
asn1_start_tag(data, ASN1_SEQUENCE(0));
- asn1_read_enumerated(data, &mod.type);
+ asn1_read_enumerated(data, &v);
+ mod.type = v;
ldap_decode_attrib(msg->mem_ctx, data, &mod.attrib);
asn1_end_tag(data);
if (!add_mod_to_array_talloc(msg->mem_ctx, &mod,
case ASN1_APPLICATION(LDAP_TAG_ModifyResponse): {
struct ldap_Result *r = &msg->r.ModifyResponse;
msg->type = LDAP_TAG_ModifyResponse;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_ModifyResponse, r);
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, r);
+ asn1_end_tag(data);
break;
}
case ASN1_APPLICATION(LDAP_TAG_AddRequest): {
struct ldap_AddRequest *r = &msg->r.AddRequest;
msg->type = LDAP_TAG_AddRequest;
- asn1_start_tag(data, ASN1_APPLICATION(LDAP_TAG_AddRequest));
+ asn1_start_tag(data, tag);
asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
r->attributes = NULL;
case ASN1_APPLICATION(LDAP_TAG_AddResponse): {
struct ldap_Result *r = &msg->r.AddResponse;
msg->type = LDAP_TAG_AddResponse;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_AddResponse, r);
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, r);
+ asn1_end_tag(data);
break;
}
- case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DeleteRequest): {
- struct ldap_DeleteRequest *r = &msg->r.DeleteRequest;
+ case ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest): {
+ struct ldap_DelRequest *r = &msg->r.DelRequest;
int len;
char *dn;
- msg->type = LDAP_TAG_DeleteRequest;
+ msg->type = LDAP_TAG_DelRequest;
asn1_start_tag(data,
- ASN1_APPLICATION_SIMPLE(LDAP_TAG_DeleteRequest));
+ ASN1_APPLICATION_SIMPLE(LDAP_TAG_DelRequest));
len = asn1_tag_remaining(data);
- dn = talloc(msg->mem_ctx, len+1);
+ dn = talloc_size(msg->mem_ctx, len+1);
if (dn == NULL)
break;
asn1_read(data, dn, len);
break;
}
- case ASN1_APPLICATION(LDAP_TAG_DeleteResponse): {
- struct ldap_Result *r = &msg->r.DeleteResponse;
- msg->type = LDAP_TAG_DeleteResponse;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_DeleteResponse, r);
+ case ASN1_APPLICATION(LDAP_TAG_DelResponse): {
+ struct ldap_Result *r = &msg->r.DelResponse;
+ msg->type = LDAP_TAG_DelResponse;
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, r);
+ asn1_end_tag(data);
break;
}
char *newsup;
asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(0));
len = asn1_tag_remaining(data);
- newsup = talloc(msg->mem_ctx, len+1);
+ newsup = talloc_size(msg->mem_ctx, len+1);
if (newsup == NULL)
break;
asn1_read(data, newsup, len);
case ASN1_APPLICATION(LDAP_TAG_ModifyDNResponse): {
struct ldap_Result *r = &msg->r.ModifyDNResponse;
msg->type = LDAP_TAG_ModifyDNResponse;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_ModifyDNResponse, r);
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, r);
+ asn1_end_tag(data);
break;
}
case ASN1_APPLICATION(LDAP_TAG_CompareRequest): {
-/* struct ldap_CompareRequest *r = &msg->r.CompareRequest; */
+ struct ldap_CompareRequest *r = &msg->r.CompareRequest;
msg->type = LDAP_TAG_CompareRequest;
+ asn1_start_tag(data,
+ ASN1_APPLICATION(LDAP_TAG_CompareRequest));
+ asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->dn);
+ asn1_start_tag(data, ASN1_SEQUENCE(0));
+ asn1_read_OctetString_talloc(msg->mem_ctx, data, &r->attribute);
+ asn1_read_OctetString(data, &r->value);
+ if (r->value.data) {
+ talloc_steal(msg->mem_ctx, r->value.data);
+ }
+ asn1_end_tag(data);
+ asn1_end_tag(data);
break;
}
case ASN1_APPLICATION(LDAP_TAG_CompareResponse): {
struct ldap_Result *r = &msg->r.CompareResponse;
msg->type = LDAP_TAG_CompareResponse;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_CompareResponse, r);
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, r);
+ asn1_end_tag(data);
break;
}
- case ASN1_APPLICATION(LDAP_TAG_AbandonRequest): {
-/* struct ldap_AbandonRequest *r = &msg->r.AbandonRequest; */
+ case ASN1_APPLICATION_SIMPLE(LDAP_TAG_AbandonRequest): {
+ struct ldap_AbandonRequest *r = &msg->r.AbandonRequest;
msg->type = LDAP_TAG_AbandonRequest;
+ asn1_start_tag(data, tag);
+ asn1_read_implicit_Integer(data, &r->messageid);
+ asn1_end_tag(data);
break;
}
DATA_BLOB tmp_blob = data_blob(NULL, 0);
msg->type = LDAP_TAG_ExtendedRequest;
- asn1_start_tag(data,ASN1_APPLICATION(LDAP_TAG_ExtendedRequest));
+ asn1_start_tag(data,tag);
if (!asn1_read_ContextSimple(data, 0, &tmp_blob)) {
return False;
}
case ASN1_APPLICATION(LDAP_TAG_ExtendedResponse): {
struct ldap_ExtendedResponse *r = &msg->r.ExtendedResponse;
msg->type = LDAP_TAG_ExtendedResponse;
- ldap_decode_response(msg->mem_ctx, data,
- LDAP_TAG_ExtendedResponse, &r->response);
+ asn1_start_tag(data, tag);
+ ldap_decode_response(msg->mem_ctx, data, &r->response);
/* I have to come across an operation that actually sends
* something back to really see what's going on. The currently
* needed pwdchange does not send anything back. */
r->name = NULL;
r->value.data = NULL;
r->value.length = 0;
+ asn1_end_tag(data);
break;
}
default:
return False;
}
+ msg->num_controls = 0;
+ msg->controls = NULL;
+
+ if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
+ int i;
+ struct ldap_Control *ctrl = NULL;
+
+ asn1_start_tag(data, ASN1_CONTEXT(0));
+
+ for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
+ asn1_start_tag(data, ASN1_SEQUENCE(0));
+
+ ctrl = talloc_realloc(msg->mem_ctx, ctrl, struct ldap_Control, i+1);
+ if (!ctrl) {
+ return False;
+ }
+ ctrl[i].oid = NULL;
+ ctrl[i].critical = False;
+ ctrl[i].value = data_blob(NULL, 0);
+
+ asn1_read_OctetString_talloc(ctrl, data, &ctrl[i].oid);
+
+ if (asn1_peek_tag(data, ASN1_BOOLEAN)) {
+ asn1_read_BOOLEAN(data, &ctrl[i].critical);
+ }
+
+ if (asn1_peek_tag(data, ASN1_OCTET_STRING)) {
+ asn1_read_OctetString(data, &ctrl[i].value);
+ if (ctrl[i].value.data) {
+ talloc_steal(msg->mem_ctx, ctrl[i].value.data);
+ }
+ }
+
+ asn1_end_tag(data);
+ }
+ msg->num_controls = i;
+ msg->controls = ctrl;
+
+ asn1_end_tag(data);
+ }
+
asn1_end_tag(data);
return ((!data->has_error) && (data->nesting == NULL));
}
BOOL ldap_parse_basic_url(TALLOC_CTX *mem_ctx, const char *url,
- char **host, uint16 *port, BOOL *ldaps)
+ char **host, uint16_t *port, BOOL *ldaps)
{
int tmp_port = 0;
- fstring protocol;
- fstring tmp_host;
+ char protocol[11];
+ char tmp_host[255];
const char *p = url;
+ int ret;
/* skip leading "URL:" (if any) */
if (strncasecmp( p, "URL:", 4) == 0) {
/* Paranoia check */
SMB_ASSERT(sizeof(protocol)>10 && sizeof(tmp_host)>254);
- sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
+ ret = sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, tmp_host, &tmp_port);
+ if (ret < 2) {
+ return False;
+ }
if (strequal(protocol, "ldap")) {
*port = 389;
if (tmp_port != 0)
*port = tmp_port;
-
+
*host = talloc_strdup(mem_ctx, tmp_host);
return (*host != NULL);
}
-
-struct ldap_connection *new_ldap_connection(void)
-{
- TALLOC_CTX *mem_ctx = talloc_init("ldap_connection");
- struct ldap_connection *result;
-
- if (mem_ctx == NULL)
- return NULL;
-
- result = talloc(mem_ctx, sizeof(*result));
-
- if (result == NULL)
- return NULL;
-
- result->mem_ctx = mem_ctx;
- result->next_msgid = 1;
- result->outstanding = NULL;
- result->searchid = 0;
- result->search_entries = NULL;
- result->auth_dn = NULL;
- result->simple_pw = NULL;
- result->gensec = NULL;
-
- return result;
-}
-
-BOOL ldap_connect(struct ldap_connection *conn, const char *url)
-{
- struct hostent *hp;
- struct in_addr ip;
-
- if (!ldap_parse_basic_url(conn->mem_ctx, url, &conn->host,
- &conn->port, &conn->ldaps))
- return False;
-
- hp = sys_gethostbyname(conn->host);
-
- if ((hp == NULL) || (hp->h_addr == NULL))
- return False;
-
- putip((char *)&ip, (char *)hp->h_addr);
-
- conn->sock = open_socket_out(SOCK_STREAM, &ip, conn->port, LDAP_CONNECTION_TIMEOUT);
-
- return (conn->sock >= 0);
-}
-
-BOOL ldap_set_simple_creds(struct ldap_connection *conn,
- const char *dn, const char *password)
-{
- conn->auth_dn = talloc_strdup(conn->mem_ctx, dn);
- conn->simple_pw = talloc_strdup(conn->mem_ctx, password);
-
- return ((conn->auth_dn != NULL) && (conn->simple_pw != NULL));
-}
-
-struct ldap_message *new_ldap_message(void)
-{
- TALLOC_CTX *mem_ctx = talloc_init("ldap_message");
- struct ldap_message *result;
-
- if (mem_ctx == NULL)
- return NULL;
-
- result = talloc(mem_ctx, sizeof(*result));
-
- if (result == NULL)
- return NULL;
-
- result->mem_ctx = mem_ctx;
- return result;
-}
-
-void destroy_ldap_message(struct ldap_message *msg)
-{
- if (msg != NULL)
- talloc_destroy(msg->mem_ctx);
-}
-
-BOOL ldap_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
- const struct timeval *endtime)
-{
- DATA_BLOB request;
- BOOL result;
- struct ldap_queue_entry *entry;
-
- msg->messageid = conn->next_msgid++;
-
- if (!ldap_encode(msg, &request))
- return False;
-
- result = (write_data_until(conn->sock, request.data, request.length,
- endtime) == request.length);
-
- data_blob_free(&request);
-
- if (!result)
- return result;
-
- /* abandon and unbind don't expect results */
-
- if ((msg->type == LDAP_TAG_AbandonRequest) ||
- (msg->type == LDAP_TAG_UnbindRequest))
- return True;
-
- entry = malloc(sizeof(*entry));
-
- if (entry == NULL)
- return False;
-
- entry->msgid = msg->messageid;
- entry->msg = NULL;
- DLIST_ADD(conn->outstanding, entry);
-
- return True;
-}
-
-BOOL ldap_receive_msg(struct ldap_connection *conn, struct ldap_message *msg,
- const struct timeval *endtime)
-{
- struct asn1_data data;
- BOOL result;
-
- if (!asn1_read_sequence_until(conn->sock, &data, endtime))
- return False;
-
- result = ldap_decode(&data, msg);
-
- asn1_free(&data);
- return result;
-}
-
-static struct ldap_message *recv_from_queue(struct ldap_connection *conn,
- int msgid)
-{
- struct ldap_queue_entry *e;
-
- for (e = conn->outstanding; e != NULL; e = e->next) {
-
- if (e->msgid == msgid) {
- struct ldap_message *result = e->msg;
- DLIST_REMOVE(conn->outstanding, e);
- SAFE_FREE(e);
- return result;
- }
- }
-
- return NULL;
-}
-
-static void add_search_entry(struct ldap_connection *conn,
- struct ldap_message *msg)
-{
- struct ldap_queue_entry *e = malloc(sizeof *e);
-
- if (e == NULL)
- return;
-
- e->msg = msg;
- DLIST_ADD_END(conn->search_entries, e, struct ldap_queue_entry *);
- return;
-}
-
-static void fill_outstanding_request(struct ldap_connection *conn,
- struct ldap_message *msg)
-{
- struct ldap_queue_entry *e;
-
- for (e = conn->outstanding; e != NULL; e = e->next) {
- if (e->msgid == msg->messageid) {
- e->msg = msg;
- return;
- }
- }
-
- /* This reply has not been expected, destroy the incoming msg */
- destroy_ldap_message(msg);
- return;
-}
-
-struct ldap_message *ldap_receive(struct ldap_connection *conn, int msgid,
- const struct timeval *endtime)
-{
- struct ldap_message *result = recv_from_queue(conn, msgid);
-
- if (result != NULL)
- return result;
-
- while (True) {
- struct asn1_data data;
- BOOL res;
-
- result = new_ldap_message();
-
- if (!asn1_read_sequence_until(conn->sock, &data, endtime))
- return NULL;
-
- res = ldap_decode(&data, result);
- asn1_free(&data);
-
- if (!res)
- return NULL;
-
- if (result->messageid == msgid)
- return result;
-
- if (result->type == LDAP_TAG_SearchResultEntry) {
- add_search_entry(conn, result);
- } else {
- fill_outstanding_request(conn, result);
- }
- }
-
- return NULL;
-}
-
-struct ldap_message *ldap_transaction(struct ldap_connection *conn,
- struct ldap_message *request)
-{
- if (!ldap_send_msg(conn, request, NULL))
- return False;
-
- return ldap_receive(conn, request->messageid, NULL);
-}
-
-int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
-{
- struct ldap_message *response;
- struct ldap_message *msg;
- const char *dn, *pw;
- int result = LDAP_OTHER;
-
- if (conn == NULL)
- return result;
-
- if (userdn) {
- dn = userdn;
- } else {
- if (conn->auth_dn) {
- dn = conn->auth_dn;
- } else {
- dn = "";
- }
- }
-
- if (password) {
- pw = password;
- } else {
- if (conn->simple_pw) {
- pw = conn->simple_pw;
- } else {
- pw = "";
- }
- }
-
- msg = new_ldap_simple_bind_msg(dn, pw);
- if (!msg)
- return result;
-
- response = ldap_transaction(conn, msg);
- if (!response) {
- destroy_ldap_message(msg);
- return result;
- }
-
- result = response->r.BindResponse.response.resultcode;
-
- destroy_ldap_message(msg);
- destroy_ldap_message(response);
-
- return result;
-}
-
-int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
-{
- NTSTATUS status;
- TALLOC_CTX *mem_ctx = NULL;
- struct ldap_message *response;
- struct ldap_message *msg;
- DATA_BLOB input = data_blob(NULL, 0);
- DATA_BLOB output = data_blob(NULL, 0);
- int result = LDAP_OTHER;
-
- if (conn == NULL)
- return result;
-
- status = gensec_client_start(conn, &conn->gensec);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
- return result;
- }
-
- status = gensec_set_domain(conn->gensec, domain);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
- domain, nt_errstr(status)));
- goto done;
- }
-
- status = gensec_set_username(conn->gensec, username);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
- username, nt_errstr(status)));
- goto done;
- }
-
- status = gensec_set_password(conn->gensec, password);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
- nt_errstr(status)));
- goto done;
- }
-
- status = gensec_set_target_hostname(conn->gensec, conn->host);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
- nt_errstr(status)));
- goto done;
- }
-
- status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
- nt_errstr(status)));
- goto done;
- }
-
- mem_ctx = talloc_init("ldap_bind_sasl");
- if (!mem_ctx)
- goto done;
-
- status = gensec_update(conn->gensec, mem_ctx,
- input,
- &output);
-
- while(1) {
- if (NT_STATUS_IS_OK(status) && output.length == 0) {
- break;
- }
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
- break;
- }
-
- msg = new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
- if (!msg)
- goto done;
-
- response = ldap_transaction(conn, msg);
- destroy_ldap_message(msg);
-
- if (!response) {
- goto done;
- }
-
- result = response->r.BindResponse.response.resultcode;
-
- if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
- break;
- }
-
- status = gensec_update(conn->gensec, mem_ctx,
- response->r.BindResponse.SASL.secblob,
- &output);
-
- destroy_ldap_message(response);
- }
-
-done:
- if (conn->gensec)
- gensec_end(&conn->gensec);
- if (mem_ctx)
- talloc_destroy(mem_ctx);
-
- return result;
-}
-
-BOOL ldap_setup_connection(struct ldap_connection *conn,
- const char *url, const char *userdn, const char *password)
-{
- int result;
-
- if (!ldap_connect(conn, url)) {
- return False;
- }
-
- result = ldap_bind_simple(conn, userdn, password);
- if (result == LDAP_SUCCESS) {
- return True;
- }
-
- return False;
-}
-
-BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
-{
- int result;
-
- if (!ldap_connect(conn, url)) {
- return False;
- }
-
- result = ldap_bind_sasl(conn, username, domain, password);
- if (result == LDAP_SUCCESS) {
- return True;
- }
-
- return False;
-}
-
-static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
- const struct timeval *endtime)
-{
- struct ldap_message *msg = new_ldap_message();
- BOOL result;
-
- if (msg == NULL)
- return False;
-
- msg->type = LDAP_TAG_AbandonRequest;
- msg->r.AbandonRequest.messageid = msgid;
-
- result = ldap_send_msg(conn, msg, endtime);
- destroy_ldap_message(msg);
- return result;
-}
-
-struct ldap_message *new_ldap_search_message(const char *base,
- enum ldap_scope scope,
- char *filter,
- int num_attributes,
- const char **attributes)
-{
- struct ldap_message *res = new_ldap_message();
-
- if (res == NULL)
- return NULL;
-
- res->type = LDAP_TAG_SearchRequest;
- res->r.SearchRequest.basedn = base;
- res->r.SearchRequest.scope = scope;
- res->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
- res->r.SearchRequest.timelimit = 0;
- res->r.SearchRequest.sizelimit = 0;
- res->r.SearchRequest.attributesonly = False;
- res->r.SearchRequest.filter = filter;
- res->r.SearchRequest.num_attributes = num_attributes;
- res->r.SearchRequest.attributes = attributes;
- return res;
-}
-
-struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
-{
- struct ldap_message *res = new_ldap_message();
-
- if (res == NULL)
- return NULL;
-
- res->type = LDAP_TAG_BindRequest;
- res->r.BindRequest.version = 3;
- res->r.BindRequest.dn = talloc_strdup(res->mem_ctx, dn);
- res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
- res->r.BindRequest.creds.password = talloc_strdup(res->mem_ctx, pw);
- return res;
-}
-
-struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
-{
- struct ldap_message *res = new_ldap_message();
-
- if (res == NULL)
- return NULL;
-
- res->type = LDAP_TAG_BindRequest;
- res->r.BindRequest.version = 3;
- res->r.BindRequest.dn = "";
- res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
- res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
- res->r.BindRequest.creds.SASL.secblob = *secblob;
- return res;
-}
-
-BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
- const struct timeval *endtime)
-{
- if ((conn->searchid != 0) &&
- (!ldap_abandon_message(conn, conn->searchid, endtime)))
- return False;
-
- conn->searchid = conn->next_msgid;
- return ldap_send_msg(conn, msg, endtime);
-}
-
-struct ldap_message *ldap_getsearchent(struct ldap_connection *conn,
- const struct timeval *endtime)
-{
- struct ldap_message *result;
-
- if (conn->search_entries != NULL) {
- struct ldap_queue_entry *e = conn->search_entries;
-
- result = e->msg;
- DLIST_REMOVE(conn->search_entries, e);
- SAFE_FREE(e);
- return result;
- }
-
- result = ldap_receive(conn, conn->searchid, endtime);
-
- if (result->type == LDAP_TAG_SearchResultEntry)
- return result;
-
- if (result->type == LDAP_TAG_SearchResultDone) {
- /* TODO: Handle Paged Results */
- destroy_ldap_message(result);
- return NULL;
- }
-
- /* TODO: Handle Search References here */
- return NULL;
-}
-
-void ldap_endsearchent(struct ldap_connection *conn,
- const struct timeval *endtime)
-{
- struct ldap_queue_entry *e;
-
- e = conn->search_entries;
-
- while (e != NULL) {
- struct ldap_queue_entry *next = e->next;
- DLIST_REMOVE(conn->search_entries, e);
- SAFE_FREE(e);
- e = next;
- }
-}
-
-struct ldap_message *ldap_searchone(struct ldap_connection *conn,
- struct ldap_message *msg,
- const struct timeval *endtime)
-{
- struct ldap_message *res1, *res2 = NULL;
- if (!ldap_setsearchent(conn, msg, endtime))
- return NULL;
-
- res1 = ldap_getsearchent(conn, endtime);
-
- if (res1 != NULL)
- res2 = ldap_getsearchent(conn, endtime);
-
- ldap_endsearchent(conn, endtime);
-
- if (res1 == NULL)
- return NULL;
-
- if (res2 != NULL) {
- /* More than one entry */
- destroy_ldap_message(res1);
- destroy_ldap_message(res2);
- return NULL;
- }
-
- return res1;
-}
-
-BOOL ldap_find_single_value(struct ldap_message *msg, const char *attr,
- DATA_BLOB *value)
-{
- int i;
- struct ldap_SearchResEntry *r = &msg->r.SearchResultEntry;
-
- if (msg->type != LDAP_TAG_SearchResultEntry)
- return False;
-
- for (i=0; i<r->num_attributes; i++) {
- if (strequal(attr, r->attributes[i].name)) {
- if (r->attributes[i].num_values != 1)
- return False;
-
- *value = r->attributes[i].values[0];
- return True;
- }
- }
- return False;
-}
-
-BOOL ldap_find_single_string(struct ldap_message *msg, const char *attr,
- TALLOC_CTX *mem_ctx, char **value)
-{
- DATA_BLOB blob;
-
- if (!ldap_find_single_value(msg, attr, &blob))
- return False;
-
- *value = talloc(mem_ctx, blob.length+1);
-
- if (*value == NULL)
- return False;
-
- memcpy(*value, blob.data, blob.length);
- (*value)[blob.length] = '\0';
- return True;
-}
-
-BOOL ldap_find_single_int(struct ldap_message *msg, const char *attr,
- int *value)
-{
- DATA_BLOB blob;
- char *val;
- int errno_save;
- BOOL res;
-
- if (!ldap_find_single_value(msg, attr, &blob))
- return False;
-
- val = malloc(blob.length+1);
- if (val == NULL)
- return False;
-
- memcpy(val, blob.data, blob.length);
- val[blob.length] = '\0';
-
- errno_save = errno;
- errno = 0;
-
- *value = strtol(val, NULL, 10);
-
- res = (errno == 0);
-
- free(val);
- errno = errno_save;
-
- return res;
-}
-
-int ldap_error(struct ldap_connection *conn)
-{
- return 0;
-}
-
-NTSTATUS ldap2nterror(int ldaperror)
-{
- return NT_STATUS_OK;
-}