Avoid the use of extensibleObject in ldap mapping backend.
[kai/samba.git] / source / dsdb / common / sidmap.c
index 3590c57b84c2208bcaf5a0b818e7c1286b5c6ab2..20bba7a0d93aa413955509da1537e58eca08261f 100644 (file)
@@ -7,7 +7,7 @@
    
    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 "includes.h"
 #include "system/passwd.h"
-#include "ads.h"
+#include "dsdb/common/flags.h"
 #include "dsdb/samdb/samdb.h"
 #include "auth/auth.h"
-#include "libcli/ldap/ldap.h"
-#include "db_wrap.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "lib/ldb/include/ldb.h"
+#include "util/util_ldb.h"
 #include "libcli/security/security.h"
+#include "param/param.h"
 
 /*
   these are used for the fallback local uid/gid to sid mapping
@@ -48,14 +49,15 @@ struct sidmap_context {
 /*
   open a sidmap context - use talloc_free to close
 */
-_PUBLIC_ struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx)
+struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx, struct event_context *ev_ctx, 
+                                  struct loadparm_context *lp_ctx)
 {
        struct sidmap_context *sidmap;
        sidmap = talloc(mem_ctx, struct sidmap_context);
        if (sidmap == NULL) {
                return NULL;
        }
-       sidmap->samctx = samdb_connect(sidmap, system_session(sidmap));
+       sidmap->samctx = samdb_connect(sidmap, ev_ctx, lp_ctx, system_session(sidmap, lp_ctx));
        if (sidmap->samctx == NULL) {
                talloc_free(sidmap);
                return NULL;
@@ -69,26 +71,26 @@ _PUBLIC_ struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx)
   check the sAMAccountType field of a search result to see if
   the account is a user account
 */
-static BOOL is_user_account(struct ldb_message *res)
+static bool is_user_account(struct ldb_message *res)
 {
        uint_t atype = samdb_result_uint(res, "sAMAccountType", 0);
        if (atype && (!(atype & ATYPE_ACCOUNT))) {
-               return False;
+               return false;
        }
-       return True;
+       return true;
 }
 
 /*
   check the sAMAccountType field of a search result to see if
   the account is a group account
 */
-static BOOL is_group_account(struct ldb_message *res)
+static bool is_group_account(struct ldb_message *res)
 {
        uint_t atype = samdb_result_uint(res, "sAMAccountType", 0);
        if (atype && atype == ATYPE_NORMAL_ACCOUNT) {
-               return False;
+               return false;
        }
-       return True;
+       return true;
 }
 
 
@@ -103,8 +105,7 @@ static NTSTATUS sidmap_primary_domain_sid(struct sidmap_context *sidmap,
        int ret;
        struct ldb_message **res = NULL;
 
-       ret = gendb_search_dn(sidmap->samctx, mem_ctx, samdb_base_dn(mem_ctx), 
-                             &res, attrs);
+       ret = gendb_search_dn(sidmap->samctx, mem_ctx, NULL, &res, attrs);
        if (ret != 1) {
                talloc_free(res);
                return NT_STATUS_NO_SUCH_DOMAIN;
@@ -123,11 +124,11 @@ static NTSTATUS sidmap_primary_domain_sid(struct sidmap_context *sidmap,
 /*
   map a sid to a unix uid
 */
-_PUBLIC_ NTSTATUS sidmap_sid_to_unixuid(struct sidmap_context *sidmap, 
-                                       struct dom_sid *sid, uid_t *uid)
+NTSTATUS sidmap_sid_to_unixuid(struct sidmap_context *sidmap,
+                                       const struct dom_sid *sid, uid_t *uid)
 {
-       const char *attrs[] = { "sAMAccountName", "unixID", 
-                               "unixName", "sAMAccountType", NULL };
+       const char *attrs[] = { "sAMAccountName", "uidNumber",
+                               "sAMAccountType", "unixName", NULL };
        int ret;
        const char *s;
        TALLOC_CTX *tmp_ctx;
@@ -137,22 +138,24 @@ _PUBLIC_ NTSTATUS sidmap_sid_to_unixuid(struct sidmap_context *sidmap,
 
        tmp_ctx = talloc_new(sidmap);
 
-       ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs, 
-                          "objectSid=%s", ldap_encode_ndr_dom_sid(tmp_ctx, sid));
+       ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
+                          "objectSid=%s",
+                          ldap_encode_ndr_dom_sid(tmp_ctx, sid));
+
        if (ret != 1) {
                goto allocated_sid;
        }
 
        /* make sure its a user, not a group */
        if (!is_user_account(res[0])) {
-               DEBUG(0,("sid_to_unixuid: sid %s is not an account!\n", 
+               DEBUG(0,("sid_to_unixuid: sid %s is not an account!\n",
                         dom_sid_string(tmp_ctx, sid)));
                talloc_free(tmp_ctx);
                return NT_STATUS_INVALID_SID;
        }
 
        /* first try to get the uid directly */
-       s = samdb_result_string(res[0], "unixID", NULL);
+       s = samdb_result_string(res[0], "uidNumber", NULL);
        if (s != NULL) {
                *uid = strtoul(s, NULL, 0);
                talloc_free(tmp_ctx);
@@ -208,21 +211,62 @@ allocated_sid:
        }
        
 
-       DEBUG(0,("sid_to_unixuid: no unixID, unixName or sAMAccountName for sid %s\n", 
+       DEBUG(0,("sid_to_unixuid: no uidNumber, unixName or sAMAccountName for sid %s\n", 
                 dom_sid_string(tmp_ctx, sid)));
 
        talloc_free(tmp_ctx);
-       return NT_STATUS_INVALID_SID;
+       return NT_STATUS_NONE_MAPPED;
 }
 
 
+/*
+  see if a sid is a group - very inefficient!
+*/
+bool sidmap_sid_is_group(struct sidmap_context *sidmap, struct dom_sid *sid)
+{
+       const char *attrs[] = { "sAMAccountType", NULL };
+       int ret;
+       TALLOC_CTX *tmp_ctx;
+       struct ldb_message **res;
+       NTSTATUS status;
+       struct dom_sid *domain_sid;
+       bool is_group;
+
+       tmp_ctx = talloc_new(sidmap);
+
+       ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs, 
+                          "objectSid=%s", ldap_encode_ndr_dom_sid(tmp_ctx, sid));
+       if (ret == 1) {
+               is_group = is_group_account(res[0]);
+               talloc_free(tmp_ctx);
+               return is_group;
+       }
+
+       status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
+               return false;
+       }
+
+       if (dom_sid_in_domain(domain_sid, sid)) {
+               uint32_t rid = sid->sub_auths[sid->num_auths-1];
+               if (rid >= SIDMAP_LOCAL_GROUP_BASE) {
+                       talloc_free(tmp_ctx);
+                       return true;
+               }
+       }
+
+       talloc_free(tmp_ctx);
+       return false;
+}
+
 /*
   map a sid to a unix gid
 */
-_PUBLIC_ NTSTATUS sidmap_sid_to_unixgid(struct sidmap_context *sidmap,
-                                       struct dom_sid *sid, gid_t *gid)
+NTSTATUS sidmap_sid_to_unixgid(struct sidmap_context *sidmap,
+                                       const struct dom_sid *sid, gid_t *gid)
 {
-       const char *attrs[] = { "sAMAccountName", "unixID", 
+       const char *attrs[] = { "sAMAccountName", "gidNumber",
                                "unixName", "sAMAccountType", NULL };
        int ret;
        const char *s;
@@ -248,7 +292,7 @@ _PUBLIC_ NTSTATUS sidmap_sid_to_unixgid(struct sidmap_context *sidmap,
        }
 
        /* first try to get the gid directly */
-       s = samdb_result_string(res[0], "unixID", NULL);
+       s = samdb_result_string(res[0], "gidNumber", NULL);
        if (s != NULL) {
                *gid = strtoul(s, NULL, 0);
                talloc_free(tmp_ctx);
@@ -300,11 +344,11 @@ allocated_sid:
                }
        }
 
-       DEBUG(0,("sid_to_unixgid: no unixID, unixName or sAMAccountName for sid %s\n", 
+       DEBUG(0,("sid_to_unixgid: no gidNumber, unixName or sAMAccountName for sid %s\n", 
                 dom_sid_string(tmp_ctx, sid)));
 
        talloc_free(tmp_ctx);
-       return NT_STATUS_INVALID_SID;
+       return NT_STATUS_NONE_MAPPED;
 }
 
 
@@ -312,9 +356,9 @@ allocated_sid:
   map a unix uid to a dom_sid
   the returned sid is allocated in the supplied mem_ctx
 */
-_PUBLIC_ NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
+NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
                                    TALLOC_CTX *mem_ctx,
-                                   uid_t uid, struct dom_sid **sid)
+                                   const uid_t uid, struct dom_sid **sid)
 {
        const char *attrs[] = { "sAMAccountName", "objectSid", "sAMAccountType", NULL };
        int ret, i;
@@ -330,7 +374,7 @@ _PUBLIC_ NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
            - check if the uid is in the dynamic uid range assigned for winbindd
              use. If it is, then look in winbindd sid mapping
              database (not implemented yet)
-           - look for a user account in samdb that has unixID set to the
+           - look for a user account in samdb that has uidNumber set to the
              given uid
            - look for a user account in samdb that has unixName or
              sAMAccountName set to the name given by getpwuid()
@@ -343,12 +387,12 @@ _PUBLIC_ NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
 
 
        /*
-         step 2: look for a user account in samdb that has unixID set to the
+         step 2: look for a user account in samdb that has uidNumber set to the
                   given uid
        */
 
        ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs, 
-                          "unixID=%u", (unsigned int)uid);
+                          "uidNumber=%u", (unsigned int)uid);
        for (i=0;i<ret;i++) {
                if (!is_user_account(res[i])) continue;
 
@@ -386,7 +430,7 @@ _PUBLIC_ NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
        */
 allocate_sid:
        if (uid > SIDMAP_MAX_LOCAL_UID) {
-               return NT_STATUS_INVALID_SID;
+               return NT_STATUS_NONE_MAPPED;
        }
 
        status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
@@ -410,9 +454,9 @@ allocate_sid:
   map a unix gid to a dom_sid
   the returned sid is allocated in the supplied mem_ctx
 */
-_PUBLIC_ NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
+NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
                                    TALLOC_CTX *mem_ctx,
-                                   gid_t gid, struct dom_sid **sid)
+                                   const gid_t gid, struct dom_sid **sid)
 {
        const char *attrs[] = { "sAMAccountName", "objectSid", "sAMAccountType", NULL };
        int ret, i;
@@ -428,7 +472,7 @@ _PUBLIC_ NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
            - check if the gid is in the dynamic gid range assigned for winbindd
              use. If it is, then look in winbindd sid mapping
              database (not implemented yet)
-           - look for a group account in samdb that has unixID set to the
+           - look for a group account in samdb that has gidNumber set to the
              given gid
            - look for a group account in samdb that has unixName or
              sAMAccountName set to the name given by getgrgid()
@@ -441,12 +485,12 @@ _PUBLIC_ NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
 
 
        /*
-         step 2: look for a group account in samdb that has unixID set to the
+         step 2: look for a group account in samdb that has gidNumber set to the
                   given gid
        */
 
        ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs, 
-                          "unixID=%u", (unsigned int)gid);
+                          "gidNumber=%u", (unsigned int)gid);
        for (i=0;i<ret;i++) {
                if (!is_group_account(res[i])) continue;
 
@@ -484,7 +528,7 @@ _PUBLIC_ NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
        */
 allocate_sid:
        if (gid > SIDMAP_MAX_LOCAL_GID) {
-               return NT_STATUS_INVALID_SID;
+               return NT_STATUS_NONE_MAPPED;
        }
 
        status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
@@ -507,17 +551,17 @@ allocate_sid:
   check if a sid is in the range of auto-allocated SIDs from our primary domain,
   and if it is, then return the name and atype
 */
-_PUBLIC_ NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap, 
+NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap, 
                                              TALLOC_CTX *mem_ctx, 
                                              const struct dom_sid *sid,
                                              const char **name,
-                                             uint32_t *atype)
+                                             enum lsa_SidType *rtype)
 {
        NTSTATUS status;
        struct dom_sid *domain_sid;
        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
-       uint32_t rid;
-
+       uint32_t rid, atype;
+       
        status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
        if (!NT_STATUS_IS_OK(status)) {
                return NT_STATUS_NO_SUCH_DOMAIN;
@@ -525,20 +569,22 @@ _PUBLIC_ NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
 
        if (!dom_sid_in_domain(domain_sid, sid)) {
                talloc_free(tmp_ctx);
-               return NT_STATUS_INVALID_SID;
+               return NT_STATUS_NONE_MAPPED;
        }
 
        talloc_free(tmp_ctx);
 
        rid = sid->sub_auths[sid->num_auths-1];
        if (rid < SIDMAP_LOCAL_USER_BASE) {
-               return NT_STATUS_INVALID_SID;
+               return NT_STATUS_NONE_MAPPED;
        }
 
        if (rid < SIDMAP_LOCAL_GROUP_BASE) {
                struct passwd *pwd;
                uid_t uid = rid - SIDMAP_LOCAL_USER_BASE;
-               *atype = ATYPE_NORMAL_ACCOUNT;
+               atype = ATYPE_NORMAL_ACCOUNT;
+               *rtype = samdb_atype_map(atype);
+
                pwd = getpwuid(uid);
                if (pwd == NULL) {
                        *name = talloc_asprintf(mem_ctx, "uid%u", uid);
@@ -548,7 +594,8 @@ _PUBLIC_ NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
        } else {
                struct group *grp;
                gid_t gid = rid - SIDMAP_LOCAL_GROUP_BASE;
-               *atype = ATYPE_LOCAL_GROUP;
+               atype = ATYPE_LOCAL_GROUP;
+               *rtype = samdb_atype_map(atype);
                grp = getgrgid(gid);
                if (grp == NULL) {
                        *name = talloc_asprintf(mem_ctx, "gid%u", gid);