#include "portable.h"
#include <stdio.h>
#include <ac/socket.h>
#include <ac/string.h>
#include "slap.h"
#include "back-netinfo.h"
dsstatus distinguishedNameToPosixNameTransform(BackendDB *be, dsdata **dst, struct berval *src, u_int32_t type, void *private)
{
dsstatus status;
struct berval ndn;
struct dsinfo *di = (struct dsinfo *)be->be_private;
u_int32_t match;
dsdata dsid;
if (!IsStringDataType(type))
return DSStatusNoData;
if (dnNormalize2(NULL, src, &ndn) != LDAP_SUCCESS)
return DSStatusInvalidPath;
status = netinfo_back_dn_pathmatch(be, &ndn, &match);
if (status != DSStatusOK)
{
ch_free(ndn.bv_val);
return status;
}
ch_free(ndn.bv_val);
dsid.type = DataTypeDirectoryID;
dsid.retain = 1;
dsid.length = 4;
match = htonl(match);
dsid.data = (void *)&match;
*dst = dsengine_convert_name(di->engine, &dsid, NameTypeDirectoryID, NameTypeUserName);
return (*dst == NULL) ? DSStatusInvalidPath : DSStatusOK;
}
dsstatus posixNameToDistinguishedNameTransform(BackendDB *be, struct berval *dst, dsdata *src, void *private)
{
struct dsinfo *di = (struct dsinfo *)be->be_private;
dsdata *dsid;
u_int32_t match;
dsid = dsengine_convert_name(di->engine, src, NameTypeUserName, NameTypeDirectoryID);
if (dsid == NULL)
return DSStatusInvalidKey;
match = dsdata_to_dsid(dsid);
dsdata_release(dsid);
return netinfo_back_global_dn(be, match, dst);
}
dsstatus appendPrefixTransform(BackendDB *be, struct berval *dst, dsdata *src, void *private)
{
struct berval *prefix = (struct berval *)private;
if (IsStringDataType(src->type))
dst->bv_len = src->length - 1 + prefix->bv_len;
else
dst->bv_len = src->length + prefix->bv_len;
dst->bv_val = ch_malloc(dst->bv_len + 1);
AC_MEMCPY(dst->bv_val, prefix->bv_val, prefix->bv_len);
AC_MEMCPY(dst->bv_val + prefix->bv_len, src->data, src->length);
dst->bv_val[dst->bv_len] = '\0';
return DSStatusOK;
}
dsstatus removeCaseIgnorePrefixTransform(BackendDB *be, dsdata **dst, struct berval *src, u_int32_t type, void *private)
{
struct berval *prefix = (struct berval *)private;
struct berval stripped;
if (strncasecmp(src->bv_val, prefix->bv_val, prefix->bv_len) != 0)
return DSStatusConstraintViolation;
stripped.bv_val = src->bv_val + prefix->bv_len;
stripped.bv_len = src->bv_len - prefix->bv_len;
*dst = berval_to_dsdata(&stripped, type);
return (*dst == NULL) ? DSStatusFailed : DSStatusOK;
}
dsstatus removeCaseExactPrefixTransform(BackendDB *be, dsdata **dst, struct berval *src, u_int32_t type, void *private)
{
struct berval *prefix = (struct berval *)private;
struct berval stripped;
if (strncmp(src->bv_val, prefix->bv_val, prefix->bv_len) != 0)
return DSStatusConstraintViolation;
stripped.bv_val = src->bv_val + prefix->bv_len;
stripped.bv_len = src->bv_len - prefix->bv_len;
*dst = berval_to_dsdata(&stripped, type);
return (*dst == NULL) ? DSStatusFailed : DSStatusOK;
}
dsstatus distinguishedNameRetrieveTransform(BackendDB *be, struct berval *dst, dsdata *src, void *private)
{
dsstatus status;
char buf[64];
struct dsinfo *di = (struct dsinfo *)be->be_private;
dsreference *ref;
u_int32_t dsid;
status = DSStatusFailed;
switch (src->type)
{
case DataTypeDSReference:
ref = dsdata_to_dsreference(src);
if (ref != NULL && ref->dn != NULL)
{
dsdata_to_berval(dst, ref->dn);
status = DSStatusOK;
}
dsreference_release(ref);
break;
case DataTypeCStr:
case DataTypeCaseCStr:
case DataTypeUTF8Str:
case DataTypeCaseUTF8Str:
dsdata_to_berval(dst, src);
status = DSStatusOK;
break;
case DataTypeDirectoryID:
status = DSStatusInvalidPath;
dsid = dsdata_to_dsid(src);
if (di->flags & DSENGINE_FLAGS_DEREFERENCE_IDS)
{
status = netinfo_back_global_dn(be, dsid, dst);
}
if (status != DSStatusOK)
{
snprintf(buf, sizeof(buf), "dSID=%lu", dsid);
dst->bv_val = ch_strdup(buf);
dst->bv_len = strlen(dst->bv_val);
status = DSStatusOK;
}
break;
default:
status = DSStatusNoData;
break;
}
return status;
}
dsstatus distinguishedNameStoreTransform(BackendDB *be, dsdata **dst, struct berval *bv, u_int32_t type, void *private)
{
struct dsinfo *di = (struct dsinfo *)be->be_private;
struct berval dn;
dsstatus status;
if (type != DataTypeDirectoryID)
return DSStatusNoData;
if (di->flags & DSENGINE_FLAGS_DEREFERENCE_IDS)
{
struct berval ndn;
u_int32_t match;
if (dnNormalize2(NULL, bv, &ndn) != LDAP_SUCCESS)
return DSStatusInvalidPath;
status = netinfo_back_dn_pathmatch(be, &ndn, &match);
if (status == DSStatusOK)
{
*dst = dsid_to_dsdata(match);
ch_free(ndn.bv_val);
return DSStatusOK;
}
ch_free(ndn.bv_val);
}
if (dnPretty2(NULL, bv, &dn) != LDAP_SUCCESS)
return DSStatusFailed;
*dst = berval_to_dsdata(&dn, DataTypeCaseUTF8Str);
ch_free(dn.bv_val);
return DSStatusOK;
}
dsstatus dsdataToBerval(BackendDB *be, struct berval *dst, dsdata *src, void *private)
{
if (dsdata_to_berval(dst, src) == NULL)
return DSStatusFailed;
if (dst->bv_len == 0)
{
ch_free(dst->bv_val);
return DSStatusNoData;
}
return DSStatusOK;
}
dsstatus bervalToDsdata(BackendDB *be, dsdata **dst, struct berval *bv, u_int32_t type, void *private)
{
*dst = berval_to_dsdata(bv, type);
if (*dst == NULL)
return DSStatusFailed;
return DSStatusOK;
}