about unification of error/return codes

Michael Adam ma at sernet.de
Thu Aug 17 12:55:19 GMT 2006


On Tue, Aug 15, 2006 at 09:35:55PM +0200, Volker Lendecke wrote:
> On Tue, Aug 15, 2006 at 03:34:07PM +0200, Michael Adam wrote:
> > For krb5, there is the problem, that all four bytes of the error
> > code are used by the kerbers error tables. But this is should be
> > no problem since there are not many krb5 error codes in total
> > (around 350); they could be mapped into the 3 free bytes of an
> > NTSTATUS.
> 
> Just found the comment above the function ads_ntstatus():
> 
> /*
>   do a rough conversion between ads error codes and NT status codes
>   we'll need to fill this in more
> */
> 
> I think this supports going with NTSTATUS even a bit more,
> even without using the trick to hide Kerberos codes directly
> in NTSTATUS. 
> 
> We can always do this, but for the important Kerberos/GSSAPI
> error codes we can do manual translation. In particular as
> Michael has found that nterr.h has a
> NT_STATUS_TIME_DIFFERENCE_AT_DC which is just handy for the
> important CLOCK_SKEW error.

Here is a suggestion for a start into this direction:

The attached patch uses the mechanism of storing the error
type inside the top byte of an NTSTATUS for LDAP like already
present with the DOS error codes. (For LDAP, this is also 
found in SAMBA_4_0.) 

System error codes (errno) don't get a special NT Status type:
They are mapped with the map_nt_error_from_unix function
in ads_ntstatus().

Kerberos/GSS error codes don't get a type either due to the 
previously mentioned problems. But the CLOCK_SKEW error is 
added to the preliminary mapping in ads_ntstaus().

In case of an LDAP type ntstatus, the nt_errstr function uses 
the ldap_err2string function. (This makes it necessary
to add $(LDAP_LIBS) for a couple of binaries in Makefile.in.)

Any opinions about this integration of LDAP error codes into NTSTATUS?

Cheers - Michael

-------------- next part --------------
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 17583)
+++ Makefile.in	(working copy)
@@ -945,7 +945,7 @@
 
 bin/profiles at EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
+	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
 
 bin/smbspool at EXEEXT@: $(CUPS_OBJ) bin/.dummy
 	@echo Linking $@
@@ -973,18 +973,18 @@
 
 bin/testparm at EXEEXT@: $(TESTPARM_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@
+	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(TESTPARM_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
 
 bin/smbstatus at EXEEXT@: $(STATUS_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(LDAP_LIBS) \
 	@POPTLIBS@
 
 bin/smbcontrol at EXEEXT@: $(SMBCONTROL_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
 	@$(CC) -DUSING_SMBCONTROL $(FLAGS) @PIE_LDFLAGS@ -o $@ \
 	$(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) \
-	$(LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@
+	$(LIBS) $(LDAP_LIBS) @LIBUNWIND_PTRACE@ @POPTLIBS@
 
 bin/smbtree at EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
@@ -1037,11 +1037,11 @@
 
 bin/eventlogadm at EXEEXT@: $(EVTLOGADM_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
+	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(EVTLOGADM_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
 
 bin/sharesec at EXEEXT@: $(SHARESEC_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ 
+	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SHARESEC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(LDAP_LIBS) @POPTLIBS@ 
 
 bin/locktest at EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
 	@echo Linking $@
@@ -1411,7 +1411,7 @@
 
 bin/wbinfo at EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@
+	@$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) $(LDAP_LIBS) @POPTLIBS@
 
 bin/ntlm_auth at EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
 		@BUILD_POPT@ bin/.dummy
Index: libsmb/nterr.c
===================================================================
--- libsmb/nterr.c	(revision 17583)
+++ libsmb/nterr.c	(working copy)
@@ -651,16 +651,19 @@
         static pstring msg;
         int idx = 0;
 
-	slprintf(msg, sizeof(msg), "NT code 0x%08x", NT_STATUS_V(nt_code));
+        if (NT_STATUS_TYPE(nt_code) == NT_STATUS_TYPE_LDAP) {
+                return ldap_err2string(NT_STATUS_LDAP_CODE(nt_code));
+	}
 
-	while (nt_errs[idx].nt_errstr != NULL) {
-		if (NT_STATUS_V(nt_errs[idx].nt_errcode) == 
-                    NT_STATUS_V(nt_code)) {
+        slprintf(msg, sizeof(msg), "NT code 0x%08x", NT_STATUS_V(nt_code));
+        while (nt_errs[idx].nt_errstr != NULL) {
+                if (NT_STATUS_V(nt_errs[idx].nt_errcode) ==
+                    NT_STATUS_V(nt_code)) 
+		{
                         return nt_errs[idx].nt_errstr;
-		}
-		idx++;
-	}
-
+                }
+                idx++;
+        }
         return msg;
 }
 
Index: include/nt_status.h
===================================================================
--- include/nt_status.h	(revision 17583)
+++ include/nt_status.h	(working copy)
@@ -66,12 +66,34 @@
         }\
 } while (0)
 
+
+/* The top byte in an NTSTATUS code is used as a type field.
+ * Windows only uses value 0xC0 as an indicator for an NT error
+ * and 0x00 for success.
+ * So we can use the type field to store other types of error codes
+ * inside the three lower bytes. 
+ * NB: The system error codes are not integrated via a type of
+ *     their own but are mapped to genuine NT error codes via 
+ *     map_nt_error_from_unix() */
+
+#define NT_STATUS_TYPE(status) ((NT_STATUS_V(status) & 0xFF000000) >> 24)
+
+#define NT_STATUS_TYPE_DOS  0xF1
+#define NT_STATUS_TYPE_LDAP 0xF2
+
 /* this defines special NTSTATUS codes to represent DOS errors.  I
    have chosen this macro to produce status codes in the invalid
    NTSTATUS range */
-#define NT_STATUS_DOS(class, code) NT_STATUS(0xF1000000 | ((class)<<16) | code)
-#define NT_STATUS_IS_DOS(status) ((NT_STATUS_V(status) & 0xFF000000) == 0xF1000000)
+#define NT_STATUS_DOS_MASK (NT_STATUS_TYPE_DOS << 24)
+#define NT_STATUS_DOS(class, code) NT_STATUS(NT_STATUS_DOS_MASK | ((class)<<16) | code)
+#define NT_STATUS_IS_DOS(status) ((NT_STATUS_V(status) & 0xFF000000) == NT_STATUS_DOS_MASK)
 #define NT_STATUS_DOS_CLASS(status) ((NT_STATUS_V(status) >> 16) & 0xFF)
 #define NT_STATUS_DOS_CODE(status) (NT_STATUS_V(status) & 0xFFFF)
 
+/* define ldap error codes as NTSTATUS codes */
+#define NT_STATUS_LDAP_MASK (NT_STATUS_TYPE_LDAP << 24)
+#define NT_STATUS_LDAP(code) NT_STATUS(NT_STATUS_LDAP_MASK | code)
+#define NT_STATUS_IS_LDAP(status) ((NT_STATUS_V(status) & 0xFF000000) == NT_STATUS_LDAP_MASK)
+#define NT_STATUS_LDAP_CODE(status) (NT_STATUS_V(status) & ~0xFF000000)
+
 #endif
Index: libads/ads_status.c
===================================================================
--- libads/ads_status.c	(revision 17583)
+++ libads/ads_status.c	(working copy)
@@ -72,18 +72,23 @@
 	if (status.error_type == ENUM_ADS_ERROR_NT){
 		return status.err.nt_status;	
 	}
+	if (status.error_type == ENUM_ADS_ERROR_SYSTEM) {
+		return map_nt_error_from_unix(status.err.rc);
+	}
 #ifdef HAVE_LDAP
-	if ((status.error_type == ENUM_ADS_ERROR_LDAP) 
-	    && (status.err.rc == LDAP_NO_MEMORY)) {
-		return NT_STATUS_NO_MEMORY;
+	if (status.error_type == ENUM_ADS_ERROR_LDAP) {
+		return NT_STATUS_LDAP(status.err.rc);
 	}
 #endif
 #ifdef HAVE_KRB5
+	/* preliminary mapping of selected krb5 error codes */
 	if (status.error_type == ENUM_ADS_ERROR_KRB5) { 
 		if (status.err.rc == KRB5KDC_ERR_PREAUTH_FAILED) {
 			return NT_STATUS_LOGON_FAILURE;
 		} else if (status.err.rc == KRB5_KDC_UNREACH) {
 			return NT_STATUS_NO_LOGON_SERVERS;
+		} else if (status.err.rc == KRB5KRB_AP_ERR_SKEW) {
+			return NT_STATUS_TIME_DIFFERENCE_AT_DC;
 		}
 	}
 #endif


More information about the samba-technical mailing list