]> granicus.if.org Git - apache/commitdiff
Added character set support to mod_auth_LDAP to allow it to convert
authorBradley Nicholes <bnicholes@apache.org>
Sat, 14 Dec 2002 00:13:15 +0000 (00:13 +0000)
committerBradley Nicholes <bnicholes@apache.org>
Sat, 14 Dec 2002 00:13:15 +0000 (00:13 +0000)
extended characters used in the user ID to UTF-8 before authenticating
against the LDAP directory. The new directive AuthLDAPCharsetConfig is
used to specify the config file that contains the character set conversion table.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97910 13f79535-47bb-0310-9956-ffa450edef68

modules/experimental/NWGNUauthldap
modules/experimental/charset.conv [new file with mode: 0644]
modules/experimental/mod_auth_ldap.c

index e9fdee8142f3e68a66b610287ae777730dbc1664..d6f892d68b237b4fd9872081810ee0fc1238aa4b 100644 (file)
@@ -246,6 +246,7 @@ nlms :: libs $(TARGET_nlm)
 #
 install :: nlms FORCE
        copy $(OBJDIR)\*.nlm $(INSTALL)\Apache2\modules\*.*
+       copy charset.conv $(INSTALL)\Apache2\conf\*.*
 
 #
 # Any specialized rules here
diff --git a/modules/experimental/charset.conv b/modules/experimental/charset.conv
new file mode 100644 (file)
index 0000000..3cd6fa9
--- /dev/null
@@ -0,0 +1,55 @@
+# Lang-abbv Charset     Language 
+#---------------------------------
+en          ISO-8859-1  English
+UTF-8       utf8        UTF-8
+Unicode     ucs         Unicode
+th          Cp874       Thai
+ja          SJIS        Japanese
+ko          Cp949       Korean
+zh          Cp950       Chinese-Traditional
+zh-cn       GB2312      Chinese-Simplified
+zh-tw       Cp950       Chinese
+cs          ISO-8859-2  Czech
+hu          ISO-8859-2  Hungarian
+hr          ISO-8859-2  Croation
+pl          ISO-8859-2  Polish
+ro          ISO-8859-2  Romanian
+sr          ISO-8859-2  Serbian
+sk          ISO-8859-2  Slovak
+sl          ISO-8859-2  Slovenian
+sq          ISO-8859-2  Albanian
+bg          ISO-8859-5  Bulgarian
+be          ISO-8859-5  Byelorussian
+mk          ISO-8859-5  Macedonian
+ru          ISO-8859-5  Russian
+uk          ISO-8859-5  Ukrainian
+ca          ISO-8859-1  Catalan
+de          ISO-8859-1  German
+da          ISO-8859-1  Danish
+fi          ISO-8859-1  Finnish
+fr          ISO-8859-1  French
+es          ISO-8859-1  Spanish
+is          ISO-8859-1  Icelandic
+it          ISO-8859-1  Italian
+nl          ISO-8859-1  Dutch
+no          ISO-8859-1  Norwegian
+pt          ISO-8859-1  Portuguese
+sv          ISO-8859-1  Swedish
+af          ISO-8859-1  Afrikaans
+eu          ISO-8859-1  Basque
+fo          ISO-8859-1  Faroese
+gl          ISO-8859-1  Galician
+ga          ISO-8859-1  Irish
+gd          ISO-8859-1  Scottish
+mt          ISO-8859-3  Maltese
+eo          ISO-8859-3  Esperanto
+el          ISO-8859-7  Greek
+tr          ISO-8859-9  Turkish
+he          ISO-8859-8  Hebrew
+iw          ISO-8859-8  Hebrew
+ar          ISO-8859-6  Arabic
+et          ISO-8859-1  Estonian
+lv          ISO-8859-2  Latvian
+lt          ISO-8859-2  Lithuanian
+                        
\ No newline at end of file
index 2fdcf6ad0ad9d08a664eb9a37c1ddaf818d267d7..2642db47d857bd300243e3f21f0ebc66e63aa1d8 100644 (file)
@@ -62,6 +62,7 @@
 
 #include <apr_ldap.h>
 #include <apr_strings.h>
+#include <apr_xlate.h>
 
 #include "ap_config.h"
 #if APR_HAVE_UNISTD_H
@@ -116,7 +117,7 @@ typedef struct {
                                           it's the exact string passed by the HTTP client */
 
     int netscapessl;                   /* True if Netscape SSL is enabled */
-    int starttls;                       /* True if StartTLS is enabled */
+    int starttls;               /* True if StartTLS is enabled */
 } mod_auth_ldap_config_t;
 
 typedef struct mod_auth_ldap_request_t {
@@ -143,6 +144,59 @@ void *mod_auth_ldap_create_dir_config(apr_pool_t *p, char *d);
 
 /* ---------------------------------------- */
 
+static apr_hash_t *charset_conversions = NULL;
+static char *to_charset = NULL;           /* UTF-8 identifier derived from the charset.conv file */
+
+/* Derive a code page ID give a language name or ID */
+static char* derive_codepage_from_lang (apr_pool_t *p, char *language)
+{
+    int lang_len;
+    int check_short = 0;
+    char *charset;
+    
+    if (!language)          // our default codepage
+        return apr_pstrdup(p, "ISO-8859-1");
+    else
+        lang_len = strlen(language);
+    
+    charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING);
+
+    if (!charset) {
+        language[2] = '\0';
+        charset = (char*) apr_hash_get(charset_conversions, language, APR_HASH_KEY_STRING);
+    }
+
+    if (charset) {
+        charset = apr_pstrdup(p, charset);
+    }
+
+    return charset;
+}
+
+static apr_xlate_t* get_conv_set (request_rec *r)
+{
+    char *lang_line = (char*)apr_table_get(r->headers_in, "accept-language");
+    char *lang;
+    apr_xlate_t *convset;
+
+    if (lang_line) {
+        lang_line = apr_pstrdup(r->pool, lang_line);
+        for (lang = lang_line;*lang;lang++) {
+            if ((*lang == ',') || (*lang == ';')) {
+                *lang = '\0';
+                break;
+            }
+        }
+        lang = derive_codepage_from_lang(r->pool, lang_line);
+
+        if (lang && (apr_xlate_open(&convset, to_charset, lang, r->pool) == APR_SUCCESS)) {
+            return convset;
+        }
+    }
+
+    return NULL;
+}
+
 
 /*
  * Build the search filter, or at least as much of the search filter that
@@ -168,6 +222,33 @@ void mod_auth_ldap_build_filter(char *filtbuf,
                                 mod_auth_ldap_config_t *sec)
 {
     char *p, *q, *filtbuf_end;
+    char *user;
+    apr_xlate_t *convset = NULL;
+    apr_size_t inbytes;
+    apr_size_t outbytes;
+    char *outbuf;
+
+    if (r->user != NULL) {
+        user = apr_pstrdup (r->pool, r->user);
+    }
+    else
+        return;
+
+    if (charset_conversions) {
+        convset = get_conv_set(r);
+    }
+
+    if (convset) {
+        inbytes = strlen(user);
+        outbytes = (inbytes+1)*3;
+        outbuf = apr_pcalloc(r->pool, outbytes);
+
+        /* Convert the user name to UTF-8.  This is only valid for LDAP v3 */
+        if (apr_xlate_conv_buffer(convset, user, &inbytes, outbuf, &outbytes) == APR_SUCCESS) {
+            user = apr_pstrdup(r->pool, outbuf);
+        }
+    }
+
     /* 
      * Create the first part of the filter, which consists of the 
      * config-supplied portions.
@@ -179,7 +260,7 @@ void mod_auth_ldap_build_filter(char *filtbuf,
      * LDAP filter metachars are escaped.
      */
     filtbuf_end = filtbuf + FILTER_LENGTH - 1;
-    for (p = r->user, q=filtbuf + strlen(filtbuf);
+    for (p = user, q=filtbuf + strlen(filtbuf);
          *p && q < filtbuf_end; *q++ = *p++) {
         if (strchr("*()\\", *p) != NULL) {
             *q++ = '\\';
@@ -270,6 +351,13 @@ start_over:
         return result;
     }
 
+    if (r->user == NULL) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
+                     "[%d] auth_ldap authenticate: no user specified", getpid());
+        util_ldap_connection_close(ldc);
+        return sec->auth_authoritative? HTTP_UNAUTHORIZED : DECLINED;
+    }
+
     /* build the username filter */
     mod_auth_ldap_build_filter(filtbuf, r, sec);
 
@@ -796,6 +884,13 @@ static const char *mod_auth_ldap_add_group_attribute(cmd_parms *cmd, void *confi
     return NULL;
 }
 
+static const char *set_charset_config(cmd_parms *cmd, void *config, const char *arg)
+{
+    ap_set_module_config(cmd->server->module_config, &auth_ldap_module,
+                         (void *)arg);
+    return NULL;
+}
+
 command_rec mod_auth_ldap_cmds[] = {
     AP_INIT_TAKE1("AuthLDAPURL", mod_auth_ldap_parse_url, NULL, OR_AUTHCFG, 
                   "URL to define LDAP connection. This should be an RFC 2255 complaint\n"
@@ -870,6 +965,10 @@ command_rec mod_auth_ldap_cmds[] = {
                  (void *)APR_OFFSETOF(mod_auth_ldap_config_t, frontpage_hack), OR_AUTHCFG,
                  "Set to 'on' to support Microsoft FrontPage"),
 
+    AP_INIT_TAKE1("AuthLDAPCharsetConfig", set_charset_config, NULL, RSRC_CONF,
+                  "Character set conversion configuration file. If omitted, character set"
+                  "conversion is disabled."),
+
 #ifdef APU_HAS_LDAP_STARTTLS
     AP_INIT_FLAG("AuthLDAPStartTLS", ap_set_flag_slot,
                  (void *)APR_OFFSETOF(mod_auth_ldap_config_t, starttls), OR_AUTHCFG,
@@ -879,8 +978,67 @@ command_rec mod_auth_ldap_cmds[] = {
     {NULL}
 };
 
+static int auth_ldap_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
+{
+    ap_configfile_t *f;
+    char l[MAX_STRING_LEN];
+    const char *charset_confname = ap_get_module_config(s->module_config,
+                                                      &auth_ldap_module);
+    apr_status_t status;
+
+    if (!charset_confname) {
+        return OK;
+    }
+
+    charset_confname = ap_server_root_relative(p, charset_confname);
+    if (!charset_confname) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
+                     "Invalid charset conversion config path %s", 
+                     (const char *)ap_get_module_config(s->module_config,
+                                                        &auth_ldap_module));
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+    if ((status = ap_pcfg_openfile(&f, ptemp, charset_confname)) 
+                != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
+                     "could not open charset conversion config file %s.", 
+                     charset_confname);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    charset_conversions = apr_hash_make(p);
+
+    while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
+        const char *ll = l;
+        char *lang;
+
+        if (l[0] == '#') {
+            continue;
+        }
+        lang = ap_getword_conf(p, &ll);
+        ap_str_tolower(lang);
+
+        if (ll[0]) {
+            char *charset = ap_getword_conf(p, &ll);
+            apr_hash_set(charset_conversions, lang, APR_HASH_KEY_STRING, charset);
+        }
+    }
+    ap_cfg_closefile(f);
+    
+    to_charset = derive_codepage_from_lang (p, "utf-8");
+    if (to_charset == NULL) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
+                     "could not find the UTF-8 charset in the file %s.", 
+                     charset_confname);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    return OK;
+}
+
 static void mod_auth_ldap_register_hooks(apr_pool_t *p)
 {
+    ap_hook_post_config(auth_ldap_post_config,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_check_user_id(mod_auth_ldap_check_user_id, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_auth_checker(mod_auth_ldap_auth_checker, NULL, NULL, APR_HOOK_MIDDLE);
 }