diff --git a/autofs-5.0.2-add-multiple-server-selection-option-fix.patch b/autofs-5.0.2-add-multiple-server-selection-option-fix.patch new file mode 100644 index 0000000..2ecb393 --- /dev/null +++ b/autofs-5.0.2-add-multiple-server-selection-option-fix.patch @@ -0,0 +1,217 @@ +diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c +index 18733f3..303b7f2 100644 +--- a/modules/cyrus-sasl.c ++++ b/modules/cyrus-sasl.c +@@ -75,6 +75,7 @@ static const char *krb5ccval = "MEMORY:_autofstkt"; + static pthread_mutex_t krb5cc_mutex = PTHREAD_MUTEX_INITIALIZER; + static unsigned int krb5cc_in_use = 0; + ++static unsigned int init_callbacks = 1; + static int sasl_log_func(void *, int, const char *); + static int getpass_func(sasl_conn_t *, void *, int, sasl_secret_t **); + static int getuser_func(void *, int, const char **, unsigned *); +@@ -386,7 +387,7 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + + debug(logopt, + "initializing kerberos ticket: client principal %s ", +- ctxt->client_princ ? "" : "autofsclient"); ++ ctxt->client_princ ? ctxt->client_princ : "autofsclient"); + + ret = krb5_init_context(&ctxt->krb5ctxt); + if (ret) { +@@ -599,8 +600,8 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c + + /* OK and CONTINUE are the only non-fatal return codes here. */ + if ((result != SASL_OK) && (result != SASL_CONTINUE)) { +- error(logopt, "sasl_client start failed with error: %s", +- sasl_errdetail(conn)); ++ warn(logopt, "sasl_client_start failed for %s", host); ++ debug(logopt, "sasl_client_start: %s", sasl_errdetail(conn)); + ldap_memfree(host); + sasl_dispose(&conn); + return NULL; +@@ -721,23 +722,30 @@ autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + sasl_conn_t *conn; + + /* Start up Cyrus SASL--only needs to be done once. */ +- if (sasl_client_init(callbacks) != SASL_OK) { ++ if (init_callbacks && sasl_client_init(callbacks) != SASL_OK) { + error(logopt, "sasl_client_init failed"); + return -1; + } ++ init_callbacks = 0; + + sasl_auth_id = ctxt->user; + sasl_auth_secret = ctxt->secret; + + /* +- * If sasl_mech was not filled in, it means that there was no +- * mechanism specified in the configuration file. Try to auto- +- * select one. ++ * If LDAP_AUTH_AUTODETECT is set, it means that there was no ++ * mechanism specified in the configuration file or auto ++ * selection has been requested, so try to auto-select an ++ * auth mechanism. + */ +- if (ctxt->sasl_mech) ++ if (!(ctxt->auth_required & LDAP_AUTH_AUTODETECT)) + conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech); +- else ++ else { ++ if (ctxt->sasl_mech) { ++ free(ctxt->sasl_mech); ++ ctxt->sasl_mech = NULL; ++ } + conn = sasl_choose_mech(logopt, ldap, ctxt); ++ } + + if (conn) { + sasl_dispose(&conn); +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 7effbf1..93f0477 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -402,8 +402,7 @@ static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s", + ctxt->auth_required, ctxt->sasl_mech); + +- if (ctxt->sasl_mech || +- (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT))) { ++ if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) { + rv = autofs_sasl_bind(logopt, ldap, ctxt); + debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv); + } else { +@@ -497,7 +496,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c + * Determine which authentication mechanism to use if we require + * authentication. + */ +- if (ctxt->auth_required & LDAP_AUTH_REQUIRED) { ++ if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) { + ldap = auth_init(logopt, uri, ctxt); + if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT) + info(logopt, +@@ -510,6 +509,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c + + if (!do_bind(logopt, ldap, ctxt)) { + unbind_ldap_connection(logopt, ldap, ctxt); ++ autofs_sasl_done(ctxt); + error(logopt, MODPREFIX "cannot bind to server"); + return NULL; + } +@@ -541,6 +541,7 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt) + while(p != ctxt->uri) { + this = list_entry(p, struct ldap_uri, list); + p = p->next; ++ debug(logopt, "trying server %s", this->uri); + ldap = connect_to_server(logopt, this->uri, ctxt); + if (ldap) { + info(logopt, "connected to uri %s", this->uri); +@@ -563,22 +564,23 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt) + + static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + { ++ struct ldap_uri *this; + LDAP *ldap; + + if (ctxt->server || !ctxt->uri) { + ldap = do_connect(logopt, ctxt->server, ctxt); + return ldap; +- } else { +- struct ldap_uri *this; +- this = list_entry(ctxt->uri->next, struct ldap_uri, list); +- ldap = do_connect(logopt, this->uri, ctxt); +- if (ldap) +- return ldap; +- /* Failed to connect, put at end of list */ +- list_del_init(&this->list); +- list_add_tail(&this->list, ctxt->uri); + } + ++ this = list_entry(ctxt->uri->next, struct ldap_uri, list); ++ ldap = do_connect(logopt, this->uri, ctxt); ++ if (ldap) ++ return ldap; ++ ++ /* Failed to connect, put at end of list */ ++ list_del_init(&this->list); ++ list_add_tail(&this->list, ctxt->uri); ++ + #ifdef WITH_SASL + autofs_sasl_done(ctxt); + #endif +@@ -844,6 +846,8 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) + ctxt->tls_required = tls_required; + ctxt->auth_required = auth_required; + ctxt->sasl_mech = authtype; ++ if (!authtype && (auth_required & LDAP_AUTH_REQUIRED)) ++ ctxt->auth_required |= LDAP_AUTH_AUTODETECT; + ctxt->user = user; + ctxt->secret = secret; + ctxt->client_princ = client_princ; +@@ -886,16 +890,6 @@ static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context * + int ret; + LDAP *ldap; + +- /* +- * First, check to see if a preferred authentication method was +- * specified by the user. parse_ldap_config will return error +- * if the permissions on the file were incorrect, or if the +- * specified authentication type is not valid. +- */ +- ret = parse_ldap_config(logopt, ctxt); +- if (ret) +- return NULL; +- + ldap = init_ldap_connection(logopt, uri, ctxt); + if (!ldap) + return NULL; +@@ -909,10 +903,8 @@ static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context * + * the credential cache and the client and service principals. + */ + ret = autofs_sasl_init(logopt, ldap, ctxt); +- if (ret) { +- ctxt->sasl_mech = NULL; ++ if (ret) + return NULL; +- } + + return ldap; + } +@@ -1134,6 +1126,8 @@ static void free_context(struct lookup_context *ctxt) + free(ctxt->user); + if (ctxt->secret) + free(ctxt->secret); ++ if (ctxt->client_princ) ++ free(ctxt->client_princ); + if (ctxt->mapname) + free(ctxt->mapname); + if (ctxt->qdn) +@@ -1184,6 +1178,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + struct lookup_context *ctxt; + char buf[MAX_ERR_BUF]; + LDAP *ldap = NULL; ++ int ret; + + *context = NULL; + +@@ -1224,6 +1219,20 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + } + } + ++#ifdef WITH_SASL ++ /* ++ * First, check to see if a preferred authentication method was ++ * specified by the user. parse_ldap_config will return error ++ * if the permissions on the file were incorrect, or if the ++ * specified authentication type is not valid. ++ */ ++ ret = parse_ldap_config(LOGOPT_NONE, ctxt); ++ if (ret) { ++ free_context(ctxt); ++ return 1; ++ } ++#endif ++ + if (ctxt->server || !ctxt->uri) { + ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt); + if (!ldap) { diff --git a/autofs-5.0.2-basedn-with-spaces-fix-2.patch b/autofs-5.0.2-basedn-with-spaces-fix-2.patch new file mode 100644 index 0000000..935010d --- /dev/null +++ b/autofs-5.0.2-basedn-with-spaces-fix-2.patch @@ -0,0 +1,29 @@ +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 5450753..36aa785 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -108,8 +108,8 @@ AT_DC ([dD][[cC]) + AT_O ([oO]) + AT_C ([cC]) + DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} +-DNNAMESTR ([[:alnum:]_.\- ]+) +-DNNAMETRM (,|{OPTWS}{NL}|{OPTWS}#.*|{OPTWS}\x00) ++DNNAMESTR1 ([[:alnum:]_.\- ]+) ++DNNAMESTR2 ([[:alnum:]_.\-]+) + + INTMAP (-hosts|-null) + MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) +@@ -282,7 +282,12 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) + return EQUAL; + } + +- {DNNAMESTR}/{DNNAMETRM} { ++ {DNNAMESTR1}/"," { ++ strcpy(master_lval.strtype, master_text); ++ return DNNAME; ++ } ++ ++ {DNNAMESTR2} { + strcpy(master_lval.strtype, master_text); + return DNNAME; + } diff --git a/autofs-5.0.2-basedn-with-spaces-fix.patch b/autofs-5.0.2-basedn-with-spaces-fix.patch new file mode 100644 index 0000000..935c553 --- /dev/null +++ b/autofs-5.0.2-basedn-with-spaces-fix.patch @@ -0,0 +1,97 @@ +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 48bc233..5450753 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -108,8 +108,8 @@ AT_DC ([dD][[cC]) + AT_O ([oO]) + AT_C ([cC]) + DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} +-DNNAMESTR ([[:alnum:]_.\-]+) +-DNNAMETRM (,|{WS}{NL}|{WS}#.*|\x00) ++DNNAMESTR ([[:alnum:]_.\- ]+) ++DNNAMETRM (,|{OPTWS}{NL}|{OPTWS}#.*|{OPTWS}\x00) + + INTMAP (-hosts|-null) + MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) +@@ -379,7 +379,13 @@ void master_set_scan_buffer(const char *buffer) + { + line = buffer; + line_pos = &line[0]; +- line_lim = line + strlen(buffer); ++ /* ++ * Ensure buffer is 1 greater than string and is zeroed before ++ * the parse so we can fit the extra NULL which allows us to ++ * explicitly match an end of line within the buffer (ie. the ++ * need for 2 NULLS when parsing in memeory buffers). ++ */ ++ line_lim = line + strlen(buffer) + 1; + } + + #define min(a,b) (((a) < (b)) ? (a) : (b)) +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index 921b32b..c093415 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -479,7 +479,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + + master->name = save_name; + } else { +- blen = path_len + 1 + ent_len + 1; ++ blen = path_len + 1 + ent_len + 2; + buffer = malloc(blen); + if (!buffer) { + error(logopt, +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 00215af..dfb3054 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -1368,7 +1368,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + goto next; + } + +- blen = strlen(*keyValue) + 1 + strlen(*values) + 1; ++ blen = strlen(*keyValue) + 1 + strlen(*values) + 2; + if (blen > PARSE_MAX_BUF) { + error(logopt, MODPREFIX "map entry too long"); + ldap_value_free(values); +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index ff8bd49..bcdaeeb 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -90,7 +90,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + char *path, *ent; + char *buffer; + char buf[MAX_ERR_BUF]; +- int cur_state; ++ int cur_state, len; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); +@@ -138,11 +138,13 @@ int lookup_read_master(struct master *master, time_t age, void *context) + + ent = ENTRY_VAL(this, 1); + +- buffer = malloc(ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 1); ++ len = ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 2; ++ buffer = malloc(len); + if (!buffer) { + logerr(MODPREFIX "could not malloc parse buffer"); + continue; + } ++ memset(buffer, 0, len); + + strcat(buffer, path); + strcat(buffer, " "); +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index 63fc8e3..7ba6940 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -178,7 +178,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen, + *(ypkey + ypkeylen) = '\0'; + *(val + vallen) = '\0'; + +- len = ypkeylen + 1 + vallen + 1; ++ len = ypkeylen + 1 + vallen + 2; + + buffer = alloca(len); + if (!buffer) { diff --git a/autofs-5.0.2-basedn-with-spaces.patch b/autofs-5.0.2-basedn-with-spaces.patch index 926628c..9b37b8f 100644 --- a/autofs-5.0.2-basedn-with-spaces.patch +++ b/autofs-5.0.2-basedn-with-spaces.patch @@ -1,105 +1,21 @@ -diff -Nurp autofs-5.0.2.orig/lib/master_tok.l autofs-5.0.2/lib/master_tok.l ---- autofs-5.0.2.orig/lib/master_tok.l 2007-11-20 15:37:48.000000000 +0900 -+++ autofs-5.0.2/lib/master_tok.l 2007-11-20 15:38:21.000000000 +0900 -@@ -108,7 +108,8 @@ AT_DC ([dD][[cC]) - AT_O ([oO]) +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 00cd223..48bc233 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -109,6 +109,7 @@ AT_O ([oO]) AT_C ([cC]) DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} --DNNAMESTR ([[:alnum:]_.\-]+) -+DNNAMESTR1 ([[:alnum:]_.\- ]+) -+DNNAMESTR2 ([[:alnum:]_.\-]+) + DNNAMESTR ([[:alnum:]_.\-]+) ++DNNAMETRM (,|{WS}{NL}|{WS}#.*|\x00) INTMAP (-hosts|-null) MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) -@@ -281,7 +282,12 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|-- +@@ -281,7 +282,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) return EQUAL; } - {DNNAMESTR} { -+ {DNNAMESTR1}/"," { -+ strcpy(master_lval.strtype, master_text); -+ return DNNAME; -+ } -+ -+ {DNNAMESTR2} { ++ {DNNAMESTR}/{DNNAMETRM} { strcpy(master_lval.strtype, master_text); return DNNAME; } -@@ -378,7 +384,13 @@ void master_set_scan_buffer(const char * - { - line = buffer; - line_pos = &line[0]; -- line_lim = line + strlen(buffer); -+ /* -+ * Ensure buffer is 1 greater than string and is zeroed before -+ * the parse so we can fit the extra NULL which allows us to -+ * explicitly match an end of line within the buffer (ie. the -+ * need for 2 NULLS when parsing in memeory buffers). -+ */ -+ line_lim = line + strlen(buffer) + 1; - } - - #define min(a,b) (((a) < (b)) ? (a) : (b)) -diff -Nurp autofs-5.0.2.orig/modules/lookup_file.c autofs-5.0.2/modules/lookup_file.c ---- autofs-5.0.2.orig/modules/lookup_file.c 2007-11-20 15:37:48.000000000 +0900 -+++ autofs-5.0.2/modules/lookup_file.c 2007-11-20 15:38:18.000000000 +0900 -@@ -479,7 +479,7 @@ int lookup_read_master(struct master *ma - - master->name = save_name; - } else { -- blen = path_len + 1 + ent_len + 1; -+ blen = path_len + 1 + ent_len + 2; - buffer = malloc(blen); - if (!buffer) { - error(logopt, -diff -Nurp autofs-5.0.2.orig/modules/lookup_ldap.c autofs-5.0.2/modules/lookup_ldap.c ---- autofs-5.0.2.orig/modules/lookup_ldap.c 2007-11-20 15:37:48.000000000 +0900 -+++ autofs-5.0.2/modules/lookup_ldap.c 2007-11-20 15:38:18.000000000 +0900 -@@ -1368,7 +1368,7 @@ int lookup_read_master(struct master *ma - goto next; - } - -- blen = strlen(*keyValue) + 1 + strlen(*values) + 1; -+ blen = strlen(*keyValue) + 1 + strlen(*values) + 2; - if (blen > PARSE_MAX_BUF) { - error(logopt, MODPREFIX "map entry too long"); - ldap_value_free(values); -diff -Nurp autofs-5.0.2.orig/modules/lookup_nisplus.c autofs-5.0.2/modules/lookup_nisplus.c ---- autofs-5.0.2.orig/modules/lookup_nisplus.c 2007-11-20 15:37:48.000000000 +0900 -+++ autofs-5.0.2/modules/lookup_nisplus.c 2007-11-20 15:38:18.000000000 +0900 -@@ -90,7 +90,7 @@ int lookup_read_master(struct master *ma - char *path, *ent; - char *buffer; - char buf[MAX_ERR_BUF]; -- int cur_state; -+ int cur_state, len; - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); - tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); -@@ -138,11 +138,13 @@ int lookup_read_master(struct master *ma - - ent = ENTRY_VAL(this, 1); - -- buffer = malloc(ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 1); -+ len = ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 2; -+ buffer = malloc(len); - if (!buffer) { - logerr(MODPREFIX "could not malloc parse buffer"); - continue; - } -+ memset(buffer, 0, len); - - strcat(buffer, path); - strcat(buffer, " "); -diff -Nurp autofs-5.0.2.orig/modules/lookup_yp.c autofs-5.0.2/modules/lookup_yp.c ---- autofs-5.0.2.orig/modules/lookup_yp.c 2007-11-20 15:37:48.000000000 +0900 -+++ autofs-5.0.2/modules/lookup_yp.c 2007-11-20 15:38:18.000000000 +0900 -@@ -178,7 +178,7 @@ int yp_all_master_callback(int status, c - *(ypkey + ypkeylen) = '\0'; - *(val + vallen) = '\0'; - -- len = ypkeylen + 1 + vallen + 1; -+ len = ypkeylen + 1 + vallen + 2; - - buffer = alloca(len); - if (!buffer) { diff --git a/autofs-5.0.2-external-cred-cache.patch b/autofs-5.0.2-external-cred-cache.patch new file mode 100644 index 0000000..8e48604 --- /dev/null +++ b/autofs-5.0.2-external-cred-cache.patch @@ -0,0 +1,392 @@ +diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h +index 5b5c475..d6a754d 100644 +--- a/include/lookup_ldap.h ++++ b/include/lookup_ldap.h +@@ -67,10 +67,10 @@ struct lookup_context { + char *user; + char *secret; + char *client_princ; ++ char *client_cc; + int kinit_done; + int kinit_successful; + #ifdef WITH_SASL +- krb5_principal krb5_client_princ; + krb5_context krb5ctxt; + krb5_ccache krb5_ccache; + sasl_conn_t *sasl_conn; +diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c +index 303b7f2..f24f46b 100644 +--- a/modules/cyrus-sasl.c ++++ b/modules/cyrus-sasl.c +@@ -72,6 +72,7 @@ + */ + static const char *krb5ccenv = "KRB5CCNAME"; + static const char *krb5ccval = "MEMORY:_autofstkt"; ++static const char *default_client = "autofsclient"; + static pthread_mutex_t krb5cc_mutex = PTHREAD_MUTEX_INITIALIZER; + static unsigned int krb5cc_in_use = 0; + +@@ -376,7 +377,7 @@ int + sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + { + krb5_error_code ret; +- krb5_principal tgs_princ, krb5_client_princ = ctxt->krb5_client_princ; ++ krb5_principal tgs_princ, krb5_client_princ; + krb5_creds my_creds; + char *tgs_name; + int status; +@@ -386,8 +387,8 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + ctxt->kinit_done = 1; + + debug(logopt, +- "initializing kerberos ticket: client principal %s ", +- ctxt->client_princ ? ctxt->client_princ : "autofsclient"); ++ "initializing kerberos ticket: client principal %s", ++ ctxt->client_princ ? ctxt->client_princ : default_client); + + ret = krb5_init_context(&ctxt->krb5ctxt); + if (ret) { +@@ -424,13 +425,12 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + "calling krb5_sname_to_principal using defaults"); + + ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL, +- "autofsclient", KRB5_NT_SRV_HST, ++ default_client, KRB5_NT_SRV_HST, + &krb5_client_princ); + if (ret) { + error(logopt, + "krb5_sname_to_principal failed for " +- "%s with error %d", +- ctxt->client_princ ? "" : "autofsclient", ret); ++ "%s with error %d", default_client, ret); + goto out_cleanup_cc; + } + +@@ -441,11 +441,11 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + debug(logopt, + "krb5_unparse_name failed with error %d", + ret); +- goto out_cleanup_cc; ++ goto out_cleanup_client_princ; + } + + debug(logopt, +- "principal used for authentication: \"%s\"", tmp_name); ++ "principal used for authentication: %s", tmp_name); + + krb5_free_unparsed_name(ctxt->krb5ctxt, tmp_name); + } +@@ -461,14 +461,14 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + if (ret) { + error(logopt, + "krb5_build_principal failed with error %d", ret); +- goto out_cleanup_cc; ++ goto out_cleanup_client_princ; + } + + ret = krb5_unparse_name(ctxt->krb5ctxt, tgs_princ, &tgs_name); + if (ret) { + error(logopt, "krb5_unparse_name failed with error %d", + ret); +- goto out_cleanup_cc; ++ goto out_cleanup_client_princ; + } + + debug(logopt, "Using tgs name %s", tgs_name); +@@ -486,7 +486,6 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + goto out_cleanup_unparse; + } + +- + status = pthread_mutex_lock(&krb5cc_mutex); + if (status) + fatal(status); +@@ -503,7 +502,7 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + if (ret) { + error(logopt, + "krb5_cc_initialize failed with error %d", ret); +- goto out_cleanup_unparse; ++ goto out_cleanup_creds; + } + + /* and store credentials for that principal */ +@@ -511,26 +510,34 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + if (ret) { + error(logopt, + "krb5_cc_store_cred failed with error %d", ret); +- goto out_cleanup_unparse; ++ goto out_cleanup_creds; + } + + /* finally, set the environment variable to point to our + * credentials cache */ + if (setenv(krb5ccenv, krb5ccval, 1) != 0) { + error(logopt, "setenv failed with %d", errno); +- goto out_cleanup_unparse; ++ goto out_cleanup_creds; + } + ctxt->kinit_successful = 1; + + debug(logopt, "Kerberos authentication was successful!"); + + krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name); ++ krb5_free_cred_contents(ctxt->krb5ctxt, &my_creds); ++ krb5_free_principal(ctxt->krb5ctxt, tgs_princ); ++ krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ); + + return 0; + +-out_cleanup_unparse: ++out_cleanup_creds: + krb5cc_in_use--; ++ krb5_free_cred_contents(ctxt->krb5ctxt, &my_creds); ++out_cleanup_unparse: ++ krb5_free_principal(ctxt->krb5ctxt, tgs_princ); + krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name); ++out_cleanup_client_princ: ++ krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ); + out_cleanup_cc: + status = pthread_mutex_lock(&krb5cc_mutex); + if (status) +@@ -554,6 +561,152 @@ out_cleanup_cc: + } + + /* ++ * Check a client given external credential cache. ++ * ++ * Returns 0 upon success. ctxt->kinit_done and ctxt->kinit_successful ++ * are set for cleanup purposes. The krb5 context and ccache entries in ++ * the lookup_context are also filled in. ++ * ++ * Upon failure, -1 is returned. ++ */ ++int ++sasl_do_kinit_ext_cc(unsigned logopt, struct lookup_context *ctxt) ++{ ++ krb5_principal def_princ; ++ krb5_principal krb5_client_princ; ++ krb5_error_code ret; ++ char *cc_princ, *client_princ; ++ ++ if (ctxt->kinit_done) ++ return 0; ++ ctxt->kinit_done = 1; ++ ++ debug(logopt, ++ "using external credential cache for auth: client principal %s", ++ ctxt->client_princ ? ctxt->client_princ : default_client); ++ ++ ret = krb5_init_context(&ctxt->krb5ctxt); ++ if (ret) { ++ error(logopt, "krb5_init_context failed with %d", ret); ++ return -1; ++ } ++ ++ ret = krb5_cc_resolve(ctxt->krb5ctxt, ctxt->client_cc, &ctxt->krb5_ccache); ++ if (ret) { ++ error(logopt, "krb5_cc_resolve failed with error %d", ++ ret); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ++ ret = krb5_cc_get_principal(ctxt->krb5ctxt, ctxt->krb5_ccache, &def_princ); ++ if (ret) { ++ error(logopt, "krb5_cc_get_principal failed with error %d", ret); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ++ ret = krb5_unparse_name(ctxt->krb5ctxt, def_princ, &cc_princ); ++ if (ret) { ++ error(logopt, "krb5_unparse_name failed with error %d", ret); ++ krb5_free_principal(ctxt->krb5ctxt, def_princ); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ++ debug(logopt, "external credential cache default principal %s", cc_princ); ++ ++ /* ++ * If the principal isn't set in the config construct the default ++ * so we can check against the default principal of the external ++ * cred cache. ++ */ ++ if (ctxt->client_princ) ++ client_princ = ctxt->client_princ; ++ else { ++ debug(logopt, ++ "calling krb5_sname_to_principal using defaults"); ++ ++ ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL, ++ default_client, KRB5_NT_SRV_HST, ++ &krb5_client_princ); ++ if (ret) { ++ error(logopt, ++ "krb5_sname_to_principal failed for " ++ "%s with error %d", default_client, ret); ++ krb5_free_principal(ctxt->krb5ctxt, def_princ); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ++ ++ ret = krb5_unparse_name(ctxt->krb5ctxt, ++ krb5_client_princ, &client_princ); ++ if (ret) { ++ debug(logopt, ++ "krb5_unparse_name failed with error %d", ++ ret); ++ krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ); ++ krb5_free_principal(ctxt->krb5ctxt, def_princ); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ++ debug(logopt, ++ "principal used for authentication: %s", client_princ); ++ ++ krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ); ++ } ++ ++ /* ++ * Check if the principal to be used matches the default principal in ++ * the external cred cache. ++ */ ++ if (strcmp(cc_princ, client_princ)) { ++ error(logopt, ++ "configured client principal %s ", ++ ctxt->client_princ); ++ error(logopt, ++ "external credential cache default principal %s", ++ cc_princ); ++ error(logopt, ++ "cannot use credential cache, external " ++ "default principal does not match configured " ++ "principal"); ++ if (!ctxt->client_princ) ++ krb5_free_unparsed_name(ctxt->krb5ctxt, client_princ); ++ krb5_free_unparsed_name(ctxt->krb5ctxt, cc_princ); ++ krb5_free_principal(ctxt->krb5ctxt, def_princ); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ++ if (!ctxt->client_princ) ++ krb5_free_unparsed_name(ctxt->krb5ctxt, client_princ); ++ krb5_free_unparsed_name(ctxt->krb5ctxt, cc_princ); ++ krb5_free_principal(ctxt->krb5ctxt, def_princ); ++ ++ /* Set the environment variable to point to the external cred cache */ ++ if (setenv(krb5ccenv, ctxt->client_cc, 1) != 0) { ++ error(logopt, "setenv failed with %d", errno); ++ krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); ++ krb5_free_context(ctxt->krb5ctxt); ++ return -1; ++ } ++ ctxt->kinit_successful = 1; ++ ++ debug(logopt, "Kerberos authentication was successful!"); ++ ++ return 0; ++} ++ ++/* + * Attempt to bind to the ldap server using a given authentication + * mechanism. ldap should be a properly initialzed ldap pointer. + * +@@ -570,7 +723,11 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c + int result; + + if (!strncmp(mech, "GSSAPI", 6)) { +- if (sasl_do_kinit(logopt, ctxt) != 0) ++ if (ctxt->client_cc) ++ result = sasl_do_kinit_ext_cc(logopt, ctxt); ++ else ++ result = sasl_do_kinit(logopt, ctxt); ++ if (result != 0) + return NULL; + } + +@@ -774,7 +931,7 @@ autofs_sasl_done(struct lookup_context *ctxt) + if (status) + fatal(status); + +- if (--krb5cc_in_use) ++ if (--krb5cc_in_use || ctxt->client_cc) + ret = krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache); + else + ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache); +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 93f0477..13fbff7 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -651,7 +651,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) + xmlNodePtr root = NULL; + char *authrequired, *auth_conf, *authtype; + char *user = NULL, *secret = NULL; +- char *client_princ = NULL; ++ char *client_princ = NULL, *client_cc = NULL; + char *usetls, *tlsrequired; + + authtype = user = secret = NULL; +@@ -840,6 +840,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) + * client. The default is "autofsclient/hostname@REALM". + */ + (void)get_property(logopt, root, "clientprinc", &client_princ); ++ (void)get_property(logopt, root, "credentialcache", &client_cc); + + ctxt->auth_conf = auth_conf; + ctxt->use_tls = use_tls; +@@ -851,6 +852,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) + ctxt->user = user; + ctxt->secret = secret; + ctxt->client_princ = client_princ; ++ ctxt->client_cc = client_cc; + + debug(logopt, MODPREFIX + "ldap authentication configured with the following options:"); +@@ -863,9 +865,10 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) + debug(logopt, MODPREFIX + "user: %s, " + "secret: %s, " +- "client principal: %s", ++ "client principal: %s " ++ "credential cache: %s", + user, secret ? "specified" : "unspecified", +- client_princ); ++ client_princ, client_cc); + + out: + xmlFreeDoc(doc); +@@ -1128,6 +1131,8 @@ static void free_context(struct lookup_context *ctxt) + free(ctxt->secret); + if (ctxt->client_princ) + free(ctxt->client_princ); ++ if (ctxt->client_cc) ++ free(ctxt->client_cc); + if (ctxt->mapname) + free(ctxt->mapname); + if (ctxt->qdn) +diff --git a/samples/autofs_ldap_auth.conf b/samples/autofs_ldap_auth.conf +index e10d1ea..a1f60c0 100644 +--- a/samples/autofs_ldap_auth.conf ++++ b/samples/autofs_ldap_auth.conf +@@ -56,6 +56,11 @@ clientprinc - When using GSSAPI authentication, this attribute is + consulted to determine the principal name to use when + authenticating to the directory server. By default, this will + be set to "autofsclient/@. ++ ++credentialcache - When using GSSAPI authentication, this attribute ++ can be used to specify an externally configured credential ++ cache that is used during authentication. By default, autofs ++ will setup a memory based credential cache. + --> + + logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN, "%s", name); ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); + if (key_len > KEY_MAX_LEN) + return NSS_STATUS_NOTFOUND; + +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 93a1b40..b8484a2 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -2053,7 +2053,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN, "%s", name); ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); + if (key_len > KEY_MAX_LEN) + return NSS_STATUS_NOTFOUND; + +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index bb1ca42..fee8b16 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -476,7 +476,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN, "%s", name); ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); + if (key_len > KEY_MAX_LEN) + return NSS_STATUS_NOTFOUND; + +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index e8ca8e8..5f4f95f 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -567,7 +567,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + debug(ap->logopt, MODPREFIX "looking up %s", name); + +- key_len = snprintf(key, KEY_MAX_LEN, "%s", name); ++ key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name); + if (key_len > KEY_MAX_LEN) + return NSS_STATUS_NOTFOUND; + diff --git a/autofs-5.0.2-foreground-logging.patch b/autofs-5.0.2-foreground-logging.patch index 9c20273..02c976e 100644 --- a/autofs-5.0.2-foreground-logging.patch +++ b/autofs-5.0.2-foreground-logging.patch @@ -1,43 +1,8 @@ -diff -up autofs-5.0.2/modules/lookup_ldap.c.foreground-logging autofs-5.0.2/modules/lookup_ldap.c ---- autofs-5.0.2/modules/lookup_ldap.c.foreground-logging 2007-09-24 14:42:28.000000000 +0800 -+++ autofs-5.0.2/modules/lookup_ldap.c 2007-09-24 14:44:18.000000000 +0800 -@@ -468,17 +468,17 @@ int parse_ldap_config(struct lookup_cont - ctxt->client_princ = client_princ; - - debug(LOGOPT_NONE, -- "ldap authentication configured with the following options:\n"); -+ "ldap authentication configured with the following options:"); - debug(LOGOPT_NONE, - "use_tls: %u, " - "tls_required: %u, " - "auth_required: %u, " -- "sasl_mech: %s\n", -+ "sasl_mech: %s", - use_tls, tls_required, auth_required, authtype); - debug(LOGOPT_NONE, - "user: %s, " - "secret: %s, " -- "client principal: %s\n", -+ "client principal: %s", - user, secret ? "specified" : "unspecified", - client_princ); - -diff -up autofs-5.0.2/modules/cyrus-sasl.c.foreground-logging autofs-5.0.2/modules/cyrus-sasl.c ---- autofs-5.0.2/modules/cyrus-sasl.c.foreground-logging 2007-06-18 15:18:08.000000000 +0800 -+++ autofs-5.0.2/modules/cyrus-sasl.c 2007-09-24 14:44:18.000000000 +0800 -@@ -197,7 +197,7 @@ get_server_SASL_mechanisms(LDAP *ld) - if (mechanisms == NULL) { - /* Well, that was a waste of time. */ - msg("No SASL authentication mechanisms are supported" -- " by the LDAP server.\n"); -+ " by the LDAP server."); - return NULL; - } - -diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/automount.c ---- autofs-5.0.2/daemon/automount.c.foreground-logging 2007-09-24 14:42:28.000000000 +0800 -+++ autofs-5.0.2/daemon/automount.c 2007-09-24 14:44:18.000000000 +0800 -@@ -58,14 +58,13 @@ unsigned int random_selection; /* use ra +diff --git a/daemon/automount.c b/daemon/automount.c +index 58f1901..51f6a8b 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -58,14 +58,13 @@ unsigned int global_random_selection; /* use random policy when selecting static int start_pipefd[2]; static int st_stat = 0; static int *pst_stat = &st_stat; @@ -63,7 +28,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ #define MAX_OPEN_FILES 10240 static int umount_all(struct autofs_point *ap, int force); -@@ -792,7 +788,6 @@ static void become_daemon(unsigned foreg +@@ -792,7 +788,6 @@ static void become_daemon(unsigned foreground) { FILE *pidfp; char buf[MAX_ERR_BUF]; @@ -71,7 +36,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ pid_t pid; /* Don't BUSY any directories unnecessarily */ -@@ -809,7 +804,9 @@ static void become_daemon(unsigned foreg +@@ -809,7 +804,9 @@ static void become_daemon(unsigned foreground) } /* Detach from foreground process */ @@ -82,7 +47,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ pid = fork(); if (pid > 0) { int r; -@@ -834,13 +831,8 @@ static void become_daemon(unsigned foreg +@@ -834,13 +831,8 @@ static void become_daemon(unsigned foreground) fprintf(stderr, "setsid: %s", estr); exit(1); } @@ -97,7 +62,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ /* Write pid file if requested */ if (pid_file) { -@@ -929,7 +921,7 @@ static pthread_t do_signals(struct maste +@@ -929,7 +921,7 @@ static pthread_t do_signals(struct master *master, int sig) if (status) fatal(status); @@ -106,7 +71,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ if (status) { error(master->default_logging, "mount state notify thread create failed"); -@@ -1043,7 +1035,6 @@ static int do_hup_signal(struct master * +@@ -1045,7 +1037,6 @@ static int do_hup_signal(struct master *master, time_t age) /* Deal with all the signal-driven events in the state machine */ static void *statemachine(void *arg) { @@ -114,7 +79,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ sigset_t signalset; int sig; -@@ -1056,15 +1047,12 @@ static void *statemachine(void *arg) +@@ -1058,15 +1049,12 @@ static void *statemachine(void *arg) switch (sig) { case SIGTERM: @@ -134,7 +99,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ break; case SIGHUP: -@@ -1179,6 +1167,10 @@ static void handle_mounts_cleanup(void * +@@ -1181,6 +1169,10 @@ static void handle_mounts_cleanup(void *arg) msg("shut down path %s", path); @@ -145,7 +110,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ return; } -@@ -1357,7 +1349,7 @@ static void usage(void) +@@ -1375,7 +1367,7 @@ static void usage(void) " -v --verbose be verbose\n" " -d --debug log debuging info\n" " -D --define define global macro variable\n" @@ -154,7 +119,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ " -r --random-multimount-selection\n" " use ramdom replicated server selection\n" " -O --global-options\n" -@@ -1632,14 +1624,6 @@ int main(int argc, char *argv[]) +@@ -1650,14 +1642,6 @@ int main(int argc, char *argv[]) } #endif @@ -169,7 +134,7 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ msg("Starting automounter version %s, master map %s", version, master_list->name); msg("using kernel protocol version %d.%02d", -@@ -1684,6 +1668,7 @@ int main(int argc, char *argv[]) +@@ -1702,6 +1686,7 @@ int main(int argc, char *argv[]) res = write(start_pipefd[1], pst_stat, sizeof(pst_stat)); close(start_pipefd[1]); @@ -177,20 +142,10 @@ diff -up autofs-5.0.2/daemon/automount.c.foreground-logging autofs-5.0.2/daemon/ statemachine(NULL); master_kill(master_list); -diff -up autofs-5.0.2/lib/master.c.foreground-logging autofs-5.0.2/lib/master.c ---- autofs-5.0.2/lib/master.c.foreground-logging 2007-09-24 14:42:28.000000000 +0800 -+++ autofs-5.0.2/lib/master.c 2007-09-24 14:44:18.000000000 +0800 -@@ -954,6 +954,7 @@ void master_notify_state_change(struct m - - switch (sig) { - case SIGTERM: -+ case SIGINT: - if (ap->state != ST_SHUTDOWN_PENDING && - ap->state != ST_SHUTDOWN_FORCE) { - next = ST_SHUTDOWN_PENDING; -diff -up autofs-5.0.2/lib/log.c.foreground-logging autofs-5.0.2/lib/log.c ---- autofs-5.0.2/lib/log.c.foreground-logging 2007-06-18 15:18:08.000000000 +0800 -+++ autofs-5.0.2/lib/log.c 2007-09-24 14:44:18.000000000 +0800 +diff --git a/lib/log.c b/lib/log.c +index e639e60..b747e12 100644 +--- a/lib/log.c ++++ b/lib/log.c @@ -27,9 +27,6 @@ #include "automount.h" @@ -201,7 +156,7 @@ diff -up autofs-5.0.2/lib/log.c.foreground-logging autofs-5.0.2/lib/log.c /* struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT; struct syslog_data *slc = &syslog_context; -@@ -134,30 +131,40 @@ static void syslog_debug(unsigned int lo +@@ -134,30 +131,40 @@ static void syslog_debug(unsigned int logopt, const char *msg, ...) va_end(ap); } @@ -256,10 +211,23 @@ diff -up autofs-5.0.2/lib/log.c.foreground-logging autofs-5.0.2/lib/log.c void log_to_syslog(void) { char buf[MAX_ERR_BUF]; -diff -up autofs-5.0.2/man/automount.8.foreground-logging autofs-5.0.2/man/automount.8 ---- autofs-5.0.2/man/automount.8.foreground-logging 2007-09-24 14:42:28.000000000 +0800 -+++ autofs-5.0.2/man/automount.8 2007-09-24 14:44:18.000000000 +0800 -@@ -47,6 +47,9 @@ Define a global macro substitution varia +diff --git a/lib/master.c b/lib/master.c +index 637ce04..abc3bc2 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -954,6 +954,7 @@ void master_notify_state_change(struct master *master, int sig) + + switch (sig) { + case SIGTERM: ++ case SIGINT: + if (ap->state != ST_SHUTDOWN_PENDING && + ap->state != ST_SHUTDOWN_FORCE) { + next = ST_SHUTDOWN_PENDING; +diff --git a/man/automount.8 b/man/automount.8 +index da67a5c..e203a3e 100644 +--- a/man/automount.8 ++++ b/man/automount.8 +@@ -47,6 +47,9 @@ Define a global macro substitution variable. Global definitions are over-ridden macro definitions of the same name specified in mount entries. .TP @@ -269,3 +237,41 @@ diff -up autofs-5.0.2/man/automount.8.foreground-logging autofs-5.0.2/man/automo .I "\-r, \-\-random-multimount-selection" Enables the use of ramdom selection when choosing a host from a list of replicated servers. +diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c +index 9aac792..68e5dd7 100644 +--- a/modules/cyrus-sasl.c ++++ b/modules/cyrus-sasl.c +@@ -197,7 +197,7 @@ get_server_SASL_mechanisms(LDAP *ld) + if (mechanisms == NULL) { + /* Well, that was a waste of time. */ + msg("No SASL authentication mechanisms are supported" +- " by the LDAP server.\n"); ++ " by the LDAP server."); + return NULL; + } + +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 4068561..c0f228b 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -857,17 +857,17 @@ int parse_ldap_config(struct lookup_context *ctxt) + ctxt->client_princ = client_princ; + + debug(LOGOPT_NONE, +- "ldap authentication configured with the following options:\n"); ++ "ldap authentication configured with the following options:"); + debug(LOGOPT_NONE, + "use_tls: %u, " + "tls_required: %u, " + "auth_required: %u, " +- "sasl_mech: %s\n", ++ "sasl_mech: %s", + use_tls, tls_required, auth_required, authtype); + debug(LOGOPT_NONE, + "user: %s, " + "secret: %s, " +- "client principal: %s\n", ++ "client principal: %s", + user, secret ? "specified" : "unspecified", + client_princ); + diff --git a/autofs-5.0.2-improve-server-unavail-fix.patch b/autofs-5.0.2-improve-server-unavail-fix.patch new file mode 100644 index 0000000..8d18e2f --- /dev/null +++ b/autofs-5.0.2-improve-server-unavail-fix.patch @@ -0,0 +1,19 @@ +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index a77068a..ab2dd0f 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -474,8 +474,12 @@ int lookup_read_master(struct master *master, time_t age, void *context) + MODPREFIX + "failed to read included master map %s", + master->name); +- fclose(f); +- return NSS_STATUS_UNAVAIL; ++ if (!master->recurse) { ++ master->depth--; ++ master->recurse = 0; ++ fclose(f); ++ return NSS_STATUS_UNAVAIL; ++ } + } + master->depth--; + master->recurse = 0; diff --git a/autofs-5.0.2-improve-server-unavail.patch b/autofs-5.0.2-improve-server-unavail.patch new file mode 100644 index 0000000..f0c1435 --- /dev/null +++ b/autofs-5.0.2-improve-server-unavail.patch @@ -0,0 +1,200 @@ +diff --git a/daemon/lookup.c b/daemon/lookup.c +index 0be10d3..eb72411 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -298,8 +298,6 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a + + status = lookup->lookup_read_map(ap, age, lookup->context); + +- map->stale = 0; +- + /* + * For maps that don't support enumeration return success + * and do whatever we must to have autofs function with an +@@ -533,6 +531,10 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time + if (result == NSS_STATUS_UNKNOWN) + continue; + ++ /* Don't try to update the map cache if it's unavailable */ ++ if (result == NSS_STATUS_UNAVAIL) ++ map->stale = 0; ++ + if (result == NSS_STATUS_SUCCESS) { + at_least_one = 1; + result = NSS_STATUS_TRYAGAIN; +@@ -553,7 +555,7 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time + } + pthread_cleanup_pop(1); + +- if (!result || at_least_one) ++ if (!result || at_least_one) + return 1; + + return 0; +diff --git a/daemon/state.c b/daemon/state.c +index cf07aac..5bccfef 100644 +--- a/daemon/state.c ++++ b/daemon/state.c +@@ -432,6 +432,7 @@ static void *do_readmap(void *arg) + me = cache_enumerate(mc, me); + } + pthread_cleanup_pop(1); ++ map->stale = 0; + map = map->next; + } + pthread_cleanup_pop(1); +diff --git a/include/automount.h b/include/automount.h +index fa5cd97..133fd32 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -121,6 +121,7 @@ struct autofs_point; + #define CHE_MISSING 0x0008 + #define CHE_COMPLETED 0x0010 + #define CHE_DUPLICATE 0x0020 ++#define CHE_UNAVAIL 0x0040 + + #define HASHSIZE 77 + #define NEGATIVE_TIMEOUT 10 +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index 550bf5c..a77068a 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -469,11 +469,14 @@ int lookup_read_master(struct master *master, time_t age, void *context) + master->recurse = 1;; + master->depth++; + status = lookup_nss_read_master(master, age); +- if (!status) ++ if (!status) { + warn(logopt, + MODPREFIX + "failed to read included master map %s", + master->name); ++ fclose(f); ++ return NSS_STATUS_UNAVAIL; ++ } + master->depth--; + master->recurse = 0; + +@@ -484,6 +487,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + if (!buffer) { + error(logopt, + MODPREFIX "could not malloc parse buffer"); ++ fclose(f); + return NSS_STATUS_UNAVAIL; + } + memset(buffer, 0, blen); +@@ -721,9 +725,12 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + + /* Gim'ee some o' that 16k stack baby !! */ + status = lookup_nss_read_map(ap, inc_source, age); +- if (!status) ++ if (!status) { + warn(ap->logopt, + "failed to read included map %s", key); ++ fclose(f); ++ return NSS_STATUS_UNAVAIL; ++ } + } else { + char *s_key; + +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index b8484a2..7effbf1 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -1755,7 +1755,7 @@ static int lookup_one(struct autofs_point *ap, + /* Initialize the LDAP context. */ + ldap = do_reconnect(ap->logopt, ctxt); + if (!ldap) +- return CHE_FAIL; ++ return CHE_UNAVAIL; + + debug(ap->logopt, + MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn); +@@ -1999,6 +1999,21 @@ static int check_map_indirect(struct autofs_point *ap, + if (ret == CHE_FAIL) { + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_NOTFOUND; ++ } else if (ret == CHE_UNAVAIL) { ++ /* ++ * If the server is down and the entry exists in the cache ++ * and belongs to this map return success and use the entry. ++ */ ++ struct mapent *exists = cache_lookup(mc, key); ++ if (exists && exists->source == source) { ++ pthread_setcancelstate(cur_state, NULL); ++ return NSS_STATUS_SUCCESS; ++ } ++ ++ warn(ap->logopt, ++ MODPREFIX "lookup for %s failed: connection failed", key); ++ ++ return NSS_STATUS_UNAVAIL; + } + pthread_setcancelstate(cur_state, NULL); + +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index fee8b16..628ffcf 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -385,9 +385,18 @@ static int check_map_indirect(struct autofs_point *ap, + return NSS_STATUS_NOTFOUND; + + if (ret < 0) { ++ /* ++ * If the server is down and the entry exists in the cache ++ * and belongs to this map return success and use the entry. ++ */ ++ exists = cache_lookup(mc, key); ++ if (exists && exists->source == source) ++ return NSS_STATUS_SUCCESS; ++ + warn(ap->logopt, + MODPREFIX "lookup for %s failed: %s", + key, nis_sperrno(-ret)); ++ + return NSS_STATUS_UNAVAIL; + } + +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index 5f4f95f..f5097dc 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -239,6 +239,9 @@ int lookup_read_master(struct master *master, time_t age, void *context) + MODPREFIX "read of master map %s failed: %s", + mapname, yperr_string(err)); + ++ if (err == YPERR_PMAP || err == YPERR_YPSERV) ++ return NSS_STATUS_UNAVAIL; ++ + return NSS_STATUS_NOTFOUND; + } + +@@ -336,6 +339,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + MODPREFIX "read of map %s failed: %s", + ap->path, yperr_string(err)); + ++ if (err == YPERR_PMAP || err == YPERR_YPSERV) ++ return NSS_STATUS_UNAVAIL; ++ + return NSS_STATUS_NOTFOUND; + } + +@@ -481,9 +487,18 @@ static int check_map_indirect(struct autofs_point *ap, + return NSS_STATUS_NOTFOUND; + + if (ret < 0) { ++ /* ++ * If the server is down and the entry exists in the cache ++ * and belongs to this map return success and use the entry. ++ */ ++ exists = cache_lookup(mc, key); ++ if (exists && exists->source == source) ++ return NSS_STATUS_SUCCESS; ++ + warn(ap->logopt, + MODPREFIX "lookup for %s failed: %s", + key, yperr_string(-ret)); ++ + return NSS_STATUS_UNAVAIL; + } + diff --git a/autofs-5.0.2-instance-stale-mark-update.patch b/autofs-5.0.2-instance-stale-mark-update.patch new file mode 100644 index 0000000..1b3f048 --- /dev/null +++ b/autofs-5.0.2-instance-stale-mark-update.patch @@ -0,0 +1,19 @@ +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index ab2dd0f..6d134cb 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -617,7 +617,13 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in + argv[1] = NULL; + + source = master_find_source_instance(current, type, fmt, argc, argv); +- if (!source) { ++ if (source) ++ /* ++ * Make sure included map age is in sync with its owner ++ * or we could incorrectly wipe out its entries. ++ */ ++ source->age = age; ++ else { + source = master_add_source_instance(current, type, fmt, age, argc, argv); + if (!source) { + free(buf); diff --git a/autofs-5.0.2-ldap-page-control.patch b/autofs-5.0.2-ldap-page-control.patch new file mode 100644 index 0000000..b0fdc3b --- /dev/null +++ b/autofs-5.0.2-ldap-page-control.patch @@ -0,0 +1,581 @@ +diff --git a/configure b/configure +index 0360086..4515fb8 100755 +--- a/configure ++++ b/configure +@@ -4580,6 +4580,102 @@ fi + + LDFLAGS="${AF_tmp_ldflags}" + ++ ++ ++for ac_func in ldap_create_page_control ldap_parse_page_control ++do ++as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` ++{ echo "$as_me:$LINENO: checking for $ac_func" >&5 ++echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } ++if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++/* Define $ac_func to an innocuous variant, in case declares $ac_func. ++ For example, HP-UX 11i declares gettimeofday. */ ++#define $ac_func innocuous_$ac_func ++ ++/* System header to define __stub macros and hopefully few prototypes, ++ which can conflict with char $ac_func (); below. ++ Prefer to if __STDC__ is defined, since ++ exists even on freestanding compilers. */ ++ ++#ifdef __STDC__ ++# include ++#else ++# include ++#endif ++ ++#undef $ac_func ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char $ac_func (); ++/* The GNU C library defines this for functions which it implements ++ to always fail with ENOSYS. Some functions are actually named ++ something starting with __ and the normal name is an alias. */ ++#if defined __stub_$ac_func || defined __stub___$ac_func ++choke me ++#endif ++ ++int ++main () ++{ ++return $ac_func (); ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext conftest$ac_exeext ++if { (ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ++ (eval "$ac_link") 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && { ++ test -z "$ac_c_werror_flag" || ++ test ! -s conftest.err ++ } && test -s conftest$ac_exeext && ++ $as_test_x conftest$ac_exeext; then ++ eval "$as_ac_var=yes" ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ eval "$as_ac_var=no" ++fi ++ ++rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ ++ conftest$ac_exeext conftest.$ac_ext ++fi ++ac_res=`eval echo '${'$as_ac_var'}'` ++ { echo "$as_me:$LINENO: result: $ac_res" >&5 ++echo "${ECHO_T}$ac_res" >&6; } ++if test `eval echo '${'$as_ac_var'}'` = yes; then ++ cat >>confdefs.h <<_ACEOF ++#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 ++_ACEOF ++ ++fi ++done ++ ++ + # + # SASL support + # configure magic taken from: +diff --git a/configure.in b/configure.in +index a83b3f1..8d5e6c9 100644 +--- a/configure.in ++++ b/configure.in +@@ -210,6 +210,8 @@ AC_SUBST(HAVE_LDAP) + AC_SUBST(LIBLDAP) + LDFLAGS="${AF_tmp_ldflags}" + ++AC_CHECK_FUNCS(ldap_create_page_control ldap_parse_page_control) ++ + # + # SASL support + # configure magic taken from: +diff --git a/include/config.h.in b/include/config.h.in +index 9669872..d8f1747 100644 +--- a/include/config.h.in ++++ b/include/config.h.in +@@ -21,6 +21,12 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_INTTYPES_H + ++/* Define to 1 if you have the `ldap_create_page_control' function. */ ++#undef HAVE_LDAP_CREATE_PAGE_CONTROL ++ ++/* Define to 1 if you have the `ldap_parse_page_control' function. */ ++#undef HAVE_LDAP_PARSE_PAGE_CONTROL ++ + /* Define if you have the Linux /proc filesystem. */ + #undef HAVE_LINUX_PROCFS + +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 65f1fda..29e26db 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -49,8 +49,79 @@ static struct ldap_schema common_schema[] = { + }; + static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); + ++struct ldap_search_params { ++ struct autofs_point *ap; ++ LDAP *ldap; ++ char *query, **attrs; ++ struct berval *cookie; ++ int morePages; ++ unsigned int totalCount; ++ LDAPMessage *result; ++ time_t age; ++}; ++ + static LDAP *auth_init(unsigned logopt, const char *, struct lookup_context *); + ++#ifndef HAVE_LDAP_CREATE_PAGE_CONTROL ++int ldap_create_page_control(LDAP *ldap, unsigned int pagesize, ++ struct berval *cookie, char isCritical, ++ LDAPControl **output) ++{ ++ BerElement *ber; ++ int rc; ++ ++ if (!ldap || !output) ++ return LDAP_PARAM_ERROR; ++ ++ ber = ber_alloc_t(LBER_USE_DER); ++ if (!ber) ++ return LDAP_NO_MEMORY; ++ ++ if (ber_printf(ber, "{io}", pagesize, ++ (cookie && cookie->bv_val) ? cookie->bv_val : "", ++ (cookie && cookie->bv_val) ? cookie->bv_len : 0) ++ == LBER_ERROR) { ++ ber_free(ber, 1); ++ return LDAP_ENCODING_ERROR; ++ } ++ ++ rc = ldap_create_control(LDAP_CONTROL_PAGEDRESULTS, ber, isCritical, output); ++ ++ return rc; ++} ++#endif /* HAVE_LDAP_CREATE_PAGE_CONTROL */ ++ ++#ifndef HAVE_LDAP_PARSE_PAGE_CONTROL ++int ldap_parse_page_control(LDAP *ldap, LDAPControl **controls, ++ unsigned int *totalcount, struct berval **cookie) ++{ ++ int i, rc; ++ BerElement *theBer; ++ LDAPControl *listCtrlp; ++ ++ for (i = 0; controls[i] != NULL; i++) { ++ if (strcmp(controls[i]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { ++ listCtrlp = controls[i]; ++ ++ theBer = ber_init(&listCtrlp->ldctl_value); ++ if (!theBer) ++ return LDAP_NO_MEMORY; ++ ++ rc = ber_scanf(theBer, "{iO}", totalcount, cookie); ++ if (rc == LBER_ERROR) { ++ ber_free(theBer, 1); ++ return LDAP_DECODING_ERROR; ++ } ++ ++ ber_free(theBer, 1); ++ return LDAP_SUCCESS; ++ } ++ } ++ ++ return LDAP_CONTROL_NOT_FOUND; ++} ++#endif /* HAVE_LDAP_PARSE_PAGE_CONTROL */ ++ + int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + int rv; +@@ -1545,80 +1616,118 @@ static int encode_percent_hack(const char *name, char **key, unsigned int use_cl + return strlen(new); + } + +-static int read_one_map(struct autofs_point *ap, +- struct lookup_context *ctxt, +- time_t age, int *result_ldap) ++static int do_paged_query(struct ldap_search_params *sp, struct lookup_context *ctxt) + { +- struct map_source *source; +- struct mapent_cache *mc; +- int rv, i, l, count; +- char buf[MAX_ERR_BUF]; +- char *query; +- LDAPMessage *result, *e; +- char *class, *info, *entry; +- struct berval **bvKey; +- struct berval **bvValues; +- char *attrs[3]; +- int scope = LDAP_SCOPE_SUBTREE; +- LDAP *ldap; +- +- source = ap->entry->current; +- ap->entry->current = NULL; +- master_source_current_signal(ap->entry); +- +- mc = source->mc; ++ struct autofs_point *ap = sp->ap; ++ LDAPControl *pageControl=NULL, *controls[2] = { NULL, NULL }; ++ LDAPControl **returnedControls = NULL; ++ static unsigned long pageSize = 1000; ++ static char pagingCriticality = 'T'; ++ int rv, scope = LDAP_SCOPE_SUBTREE; ++ ++ if (sp->morePages == TRUE) ++ goto do_paged; ++ ++ rv = ldap_search_s(sp->ldap, ctxt->qdn, scope, sp->query, sp->attrs, 0, &sp->result); ++ if ((rv != LDAP_SUCCESS) || !sp->result) { ++ /* ++ * Check for Size Limit exceeded and force run through loop ++ * and requery using page control. ++ */ ++ if (rv == LDAP_SIZELIMIT_EXCEEDED) ++ sp->morePages = TRUE; ++ else { ++ debug(ap->logopt, ++ MODPREFIX "query failed for %s: %s", ++ sp->query, ldap_err2string(rv)); ++ return rv; ++ } ++ } ++ return rv; + +- class = ctxt->schema->entry_class; +- entry = ctxt->schema->entry_attr; +- info = ctxt->schema->value_attr; ++do_paged: ++ /* we need to use page controls so requery LDAP */ ++ debug(ap->logopt, MODPREFIX "geting page of results"); + +- attrs[0] = entry; +- attrs[1] = info; +- attrs[2] = NULL; ++ rv = ldap_create_page_control(sp->ldap, pageSize, sp->cookie, ++ pagingCriticality, &pageControl); ++ if (rv != LDAP_SUCCESS) { ++ warn(ap->logopt, MODPREFIX "failed to create page control"); ++ return rv; ++ } + +- /* Build a query string. */ +- l = strlen("(objectclass=)") + strlen(class) + 1; ++ /* Insert the control into a list to be passed to the search. */ ++ controls[0] = pageControl; + +- query = alloca(l); +- if (query == NULL) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr(MODPREFIX "malloc: %s", estr); +- return NSS_STATUS_UNAVAIL; ++ /* Search for entries in the directory using the parmeters. */ ++ rv = ldap_search_ext_s(sp->ldap, ++ ctxt->qdn, scope, sp->query, sp->attrs, ++ 0, controls, NULL, NULL, 0, &sp->result); ++ if ((rv != LDAP_SUCCESS) && (rv != LDAP_PARTIAL_RESULTS)) { ++ debug(ap->logopt, ++ MODPREFIX "query failed for %s: %s", ++ sp->query, ldap_err2string(rv)); ++ ldap_control_free(pageControl); ++ return rv; + } + +- if (sprintf(query, "(objectclass=%s)", class) >= l) { +- error(ap->logopt, MODPREFIX "error forming query string"); +- return NSS_STATUS_UNAVAIL; ++ /* Parse the results to retrieve the contols being returned. */ ++ rv = ldap_parse_result(sp->ldap, sp->result, ++ NULL, NULL, NULL, NULL, ++ &returnedControls, FALSE); ++ if (sp->cookie != NULL) { ++ ber_bvfree(sp->cookie); ++ sp->cookie = NULL; + } +- query[l] = '\0'; + +- /* Initialize the LDAP context. */ +- ldap = do_reconnect(ap->logopt, ctxt); +- if (!ldap) +- return NSS_STATUS_UNAVAIL; ++ /* ++ * Parse the page control returned to get the cookie and ++ * determine whether there are more pages. ++ */ ++ rv = ldap_parse_page_control(sp->ldap, ++ returnedControls, &sp->totalCount, ++ &sp->cookie); ++ if (sp->cookie && sp->cookie->bv_val && strlen(sp->cookie->bv_val)) ++ sp->morePages = TRUE; ++ else ++ sp->morePages = FALSE; + +- /* Look around. */ +- debug(ap->logopt, +- MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn); ++ /* Cleanup the controls used. */ ++ if (returnedControls) ++ ldap_controls_free(returnedControls); + +- rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result); ++ ldap_control_free(pageControl); + +- if ((rv != LDAP_SUCCESS) || !result) { +- debug(ap->logopt, +- MODPREFIX "query failed for %s: %s", +- query, ldap_err2string(rv)); +- unbind_ldap_connection(ap->logopt, ldap, ctxt); +- *result_ldap = rv; +- return NSS_STATUS_NOTFOUND; +- } ++ return rv; ++} + +- e = ldap_first_entry(ldap, result); ++static int do_get_entries(struct ldap_search_params *sp, struct map_source *source, struct lookup_context *ctxt) ++{ ++ struct autofs_point *ap = sp->ap; ++ struct mapent_cache *mc = source->mc; ++ char buf[MAX_ERR_BUF]; ++ struct berval **bvKey; ++ struct berval **bvValues; ++ LDAPMessage *e; ++ char *class, *info, *entry; ++ int rv, ret; ++ int i, count; ++ ++ class = ctxt->schema->entry_class; ++ entry = ctxt->schema->entry_attr; ++ info = ctxt->schema->value_attr; ++ ++ e = ldap_first_entry(sp->ldap, sp->result); + if (!e) { + debug(ap->logopt, +- MODPREFIX "query succeeded, no matches for %s", query); +- ldap_msgfree(result); +- unbind_ldap_connection(ap->logopt, ldap, ctxt); +- return NSS_STATUS_NOTFOUND; ++ MODPREFIX "query succeeded, no matches for %s", ++ sp->query); ++ ret = ldap_parse_result(sp->ldap, sp->result, ++ &rv, NULL, NULL, NULL, NULL, 0); ++ if (ret == LDAP_SUCCESS) ++ return rv; ++ else ++ return LDAP_OPERATIONS_ERROR; + } else + debug(ap->logopt, MODPREFIX "examining entries"); + +@@ -1629,10 +1738,21 @@ static int read_one_map(struct autofs_point *ap, + ber_len_t k_len; + char *s_key; + +- bvKey = ldap_get_values_len(ldap, e, entry); +- ++ bvKey = ldap_get_values_len(sp->ldap, e, entry); + if (!bvKey || !*bvKey) { +- e = ldap_next_entry(ldap, e); ++ e = ldap_next_entry(sp->ldap, e); ++ if (!e) { ++ debug(ap->logopt, MODPREFIX ++ "failed to get next entry for query %s", ++ sp->query); ++ ret = ldap_parse_result(sp->ldap, ++ sp->result, &rv, ++ NULL, NULL, NULL, NULL, 0); ++ if (ret == LDAP_SUCCESS) ++ return rv; ++ else ++ return LDAP_OPERATIONS_ERROR; ++ } + continue; + } + +@@ -1697,8 +1817,7 @@ static int read_one_map(struct autofs_point *ap, + + if (!k_val) { + error(ap->logopt, +- MODPREFIX +- "invalid entry %.*s - ignoring", ++ MODPREFIX "invalid entry %.*s - ignoring", + bvKey[0]->bv_len, bvKey[0]->bv_val); + goto next; + } +@@ -1721,10 +1840,10 @@ static int read_one_map(struct autofs_point *ap, + goto next; + } + +- bvValues = ldap_get_values_len(ldap, e, info); ++ bvValues = ldap_get_values_len(sp->ldap, e, info); + if (!bvValues || !*bvValues) { + debug(ap->logopt, +- MODPREFIX "no %s defined for %s", info, query); ++ MODPREFIX "no %s defined for %s", info, sp->query); + goto next; + } + +@@ -1737,7 +1856,6 @@ static int read_one_map(struct autofs_point *ap, + * options or the actual order of entries causes problems + * it won't be supported. Perhaps someone can instruct us + * how to force an ordering. +- * + */ + count = ldap_count_values_len(bvValues); + for (i = 0; i < count; i++) { +@@ -1807,7 +1925,7 @@ static int read_one_map(struct autofs_point *ap, + } + + cache_writelock(mc); +- cache_update(mc, source, s_key, mapent, age); ++ cache_update(mc, source, s_key, mapent, sp->age); + cache_unlock(mc); + + free(s_key); +@@ -1818,14 +1936,112 @@ next: + } + + ldap_value_free_len(bvKey); +- e = ldap_next_entry(ldap, e); ++ e = ldap_next_entry(sp->ldap, e); ++ if (!e) { ++ debug(ap->logopt, MODPREFIX ++ "failed to get next entry for query %s", ++ sp->query); ++ ret = ldap_parse_result(sp->ldap, ++ sp->result, &rv, ++ NULL, NULL, NULL, NULL, 0); ++ if (ret == LDAP_SUCCESS) ++ return rv; ++ else ++ return LDAP_OPERATIONS_ERROR; ++ } ++ } ++ ++ return LDAP_SUCCESS; ++} ++ ++ ++static int read_one_map(struct autofs_point *ap, ++ struct lookup_context *ctxt, ++ time_t age, int *result_ldap) ++{ ++ struct map_source *source; ++ struct ldap_search_params sp; ++ char buf[MAX_ERR_BUF]; ++ char *class, *info, *entry; ++ char *attrs[3]; ++ int rv, l; ++ ++ source = ap->entry->current; ++ ap->entry->current = NULL; ++ master_source_current_signal(ap->entry); ++ ++ sp.ap = ap; ++ sp.age = age; ++ ++ class = ctxt->schema->entry_class; ++ entry = ctxt->schema->entry_attr; ++ info = ctxt->schema->value_attr; ++ ++ attrs[0] = entry; ++ attrs[1] = info; ++ attrs[2] = NULL; ++ sp.attrs = attrs; ++ ++ /* Build a query string. */ ++ l = strlen("(objectclass=)") + strlen(class) + 1; ++ ++ sp.query = alloca(l); ++ if (sp.query == NULL) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ logerr(MODPREFIX "malloc: %s", estr); ++ return NSS_STATUS_UNAVAIL; ++ } ++ ++ if (sprintf(sp.query, "(objectclass=%s)", class) >= l) { ++ error(ap->logopt, MODPREFIX "error forming query string"); ++ return NSS_STATUS_UNAVAIL; + } ++ sp.query[l] = '\0'; ++ ++ /* Initialize the LDAP context. */ ++ sp.ldap = do_reconnect(ap->logopt, ctxt); ++ if (!sp.ldap) ++ return NSS_STATUS_UNAVAIL; ++ ++ /* Look around. */ ++ debug(ap->logopt, ++ MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, ctxt->qdn); ++ ++ sp.cookie = NULL; ++ sp.morePages = FALSE; ++ sp.totalCount = 0; ++ sp.result = NULL; ++ ++ do { ++ rv = do_paged_query(&sp, ctxt); ++ if (rv == LDAP_SIZELIMIT_EXCEEDED) ++ { ++ debug(ap->logopt, MODPREFIX "result size exceed"); ++ if (sp.result) ++ ldap_msgfree(sp.result); ++ ++ continue; ++ } ++ ++ if (rv != LDAP_SUCCESS || !sp.result) { ++ unbind_ldap_connection(ap->logopt, sp.ldap, ctxt); ++ *result_ldap = rv; ++ return NSS_STATUS_UNAVAIL; ++ } ++ ++ rv = do_get_entries(&sp, source, ctxt); ++ if (rv != LDAP_SUCCESS) { ++ ldap_msgfree(sp.result); ++ unbind_ldap_connection(ap->logopt, sp.ldap, ctxt); ++ *result_ldap = rv; ++ return NSS_STATUS_NOTFOUND; ++ } ++ ldap_msgfree(sp.result); ++ } while (sp.morePages == TRUE); + + debug(ap->logopt, MODPREFIX "done updating map"); + +- /* Clean up. */ +- ldap_msgfree(result); +- unbind_ldap_connection(ap->logopt, ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, sp.ldap, ctxt); + + source->age = age; + diff --git a/autofs-5.0.2-ldap-search-basedn-list-fix.patch b/autofs-5.0.2-ldap-search-basedn-list-fix.patch new file mode 100644 index 0000000..aa417d3 --- /dev/null +++ b/autofs-5.0.2-ldap-search-basedn-list-fix.patch @@ -0,0 +1,127 @@ +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 29e26db..0723fd8 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -261,7 +261,7 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt + { + char buf[PARSE_MAX_BUF]; + char *query, *dn, *qdn; +- LDAPMessage *result = NULL, *e; ++ LDAPMessage *result, *e; + struct ldap_searchdn *sdns = NULL; + char *attrs[2]; + struct berval **value; +@@ -319,52 +319,71 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt + } + } + +- if (!ctxt->sdns) ++ dn = NULL; ++ if (!ctxt->sdns) { + rv = ldap_search_s(ldap, ctxt->base, + scope, query, attrs, 0, &result); +- else { ++ if ((rv != LDAP_SUCCESS) || !result) { ++ error(logopt, ++ MODPREFIX "query failed for %s: %s", ++ query, ldap_err2string(rv)); ++ return 0; ++ } ++ ++ e = ldap_first_entry(ldap, result); ++ if (e && (value = ldap_get_values_len(ldap, e, key))) { ++ ldap_value_free_len(value); ++ dn = ldap_get_dn(ldap, e); ++ debug(logopt, MODPREFIX "found query dn %s", dn); ++ } else { ++ debug(logopt, ++ MODPREFIX "query succeeded, no matches for %s", ++ query); ++ ldap_msgfree(result); ++ return 0; ++ } ++ } else { + struct ldap_searchdn *this = ctxt->sdns; + + debug(logopt, MODPREFIX "check search base list"); + ++ result = NULL; + while (this) { + rv = ldap_search_s(ldap, this->basedn, + scope, query, attrs, 0, &result); +- + if ((rv == LDAP_SUCCESS) && result) { + debug(logopt, MODPREFIX + "found search base under %s", + this->basedn); +- break; ++ ++ e = ldap_first_entry(ldap, result); ++ if (e && (value = ldap_get_values_len(ldap, e, key))) { ++ ldap_value_free_len(value); ++ dn = ldap_get_dn(ldap, e); ++ debug(logopt, MODPREFIX "found query dn %s", dn); ++ break; ++ } else { ++ debug(logopt, ++ MODPREFIX "query succeeded, no matches for %s", ++ query); ++ ldap_msgfree(result); ++ result = NULL; ++ } ++ } else { ++ error(logopt, ++ MODPREFIX "query failed for search dn %s: %s", ++ this->basedn, ldap_err2string(rv)); + } + + this = this->next; +- +- if (result) { +- ldap_msgfree(result); +- result = NULL; +- } + } +- } +- +- if ((rv != LDAP_SUCCESS) || !result) { +- error(logopt, +- MODPREFIX "query failed for %s: %s", +- query, ldap_err2string(rv)); +- return 0; +- } + +- e = ldap_first_entry(ldap, result); +- if (e && (value = ldap_get_values_len(ldap, e, key))) { +- ldap_value_free_len(value); +- dn = ldap_get_dn(ldap, e); +- debug(logopt, MODPREFIX "found query dn %s", dn); +- } else { +- debug(logopt, +- MODPREFIX "query succeeded, no matches for %s", +- query); +- ldap_msgfree(result); +- return 0; ++ if (!result) { ++ ldap_msgfree(result); ++ error(logopt, ++ MODPREFIX "failed to find query dn under search base dns"); ++ return 0; ++ } + } + + qdn = strdup(dn); +@@ -1290,8 +1309,12 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + validate_uris(uris); + if (!list_empty(uris)) + ctxt->uri = uris; +- else ++ else { ++ error(LOGOPT_ANY, ++ "no valid uris found in config list" ++ ", using default system config"); + free(uris); ++ } + } + } + diff --git a/autofs-5.0.2-ldap-search-basedn-list.patch b/autofs-5.0.2-ldap-search-basedn-list.patch index 7bddb26..f291a5f 100644 --- a/autofs-5.0.2-ldap-search-basedn-list.patch +++ b/autofs-5.0.2-ldap-search-basedn-list.patch @@ -1,24 +1,30 @@ -diff -up autofs-5.0.2/redhat/autofs.sysconfig.in.ldap-search-basedn-list autofs-5.0.2/redhat/autofs.sysconfig.in ---- autofs-5.0.2/redhat/autofs.sysconfig.in.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/redhat/autofs.sysconfig.in 2007-11-20 14:08:26.000000000 +0900 -@@ -21,6 +21,14 @@ BROWSE_MODE="no" - # - #LOGGING="none" - # -+# Define base dn for map dn lookup. -+# -+# SEARCH_BASE - base dn to use for searching for map search dn. -+# Multiple entries can be given and they are checked -+# in the order they occur here. -+# -+#SEARCH_BASE="" -+# - # Define the LDAP schema to used for lookups - # - # If no schema is set autofs will check each of the schemas -diff -up autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list autofs-5.0.2/include/lookup_ldap.h ---- autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/include/lookup_ldap.h 2007-11-20 14:08:26.000000000 +0900 +diff --git a/include/defaults.h b/include/defaults.h +index 9aec11a..0984b1c 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -37,6 +37,9 @@ + #define DEFAULT_APPEND_OPTIONS 1 + #define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf" + ++struct ldap_schema; ++struct ldap_searchdn; ++ + unsigned int defaults_read_config(void); + const char *defaults_get_master_map(void); + unsigned int defaults_get_timeout(void); +@@ -45,6 +48,8 @@ unsigned int defaults_get_logging(void); + const char *defaults_get_ldap_server(void); + struct ldap_schema *defaults_get_default_schema(void); + struct ldap_schema *defaults_get_schema(void); ++struct ldap_searchdn *defaults_get_searchdns(void); ++void defaults_free_searchdns(struct ldap_searchdn *); + unsigned int defaults_get_append_options(void); + const char *defaults_get_auth_conf_file(void); + +diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h +index 1378b9e..1a924be 100644 +--- a/include/lookup_ldap.h ++++ b/include/lookup_ldap.h @@ -18,6 +18,11 @@ struct ldap_schema { char *value_attr; }; @@ -42,32 +48,257 @@ diff -up autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list autofs-5.0.2 /* TLS and SASL authentication information */ char *auth_conf; unsigned use_tls; -diff -up autofs-5.0.2/include/defaults.h.ldap-search-basedn-list autofs-5.0.2/include/defaults.h ---- autofs-5.0.2/include/defaults.h.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/include/defaults.h 2007-11-20 14:08:26.000000000 +0900 -@@ -37,6 +37,9 @@ - #define DEFAULT_APPEND_OPTIONS 1 - #define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf" +diff --git a/lib/defaults.c b/lib/defaults.c +index b146f13..c2f86c0 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -32,6 +32,8 @@ -+struct ldap_schema; -+struct ldap_searchdn; + #define ENV_LDAP_SERVER "LDAP_SERVER" + ++#define SEARCH_BASE "SEARCH_BASE" + - unsigned int defaults_read_config(void); - const char *defaults_get_master_map(void); - unsigned int defaults_get_timeout(void); -@@ -45,6 +48,8 @@ unsigned int defaults_get_logging(void); - const char *defaults_get_ldap_server(void); - struct ldap_schema *defaults_get_default_schema(void); - struct ldap_schema *defaults_get_schema(void); -+struct ldap_searchdn *defaults_get_searchdns(void); -+void defaults_free_searchdns(struct ldap_searchdn *); - unsigned int defaults_get_append_options(void); - const char *defaults_get_auth_conf_file(void); + #define ENV_NAME_MAP_OBJ_CLASS "MAP_OBJECT_CLASS" + #define ENV_NAME_ENTRY_OBJ_CLASS "ENTRY_OBJECT_CLASS" + #define ENV_NAME_MAP_ATTR "MAP_ATTRIBUTE" +@@ -130,6 +132,52 @@ static int check_set_config_value(const char *res, const char *name, const char + return 0; + } + ++static int parse_line(char *line, char **res, char **value) ++{ ++ char *key, *val, *trailer; ++ int len; ++ ++ key = line; ++ ++ if (*key == '#' || !isalpha(*key)) ++ return 0; ++ ++ while (*key && *key == ' ') ++ key++; ++ ++ if (!key) ++ return 0; ++ ++ if (!(val = strchr(key, '='))) ++ return 0; ++ ++ *val++ = '\0'; ++ ++ while (*val && (*val == '"' || isblank(*val))) ++ val++; ++ ++ len = strlen(val); ++ ++ if (val[len - 1] == '\n') { ++ val[len - 1] = '\0'; ++ len--; ++ } ++ ++ trailer = strchr(val, '#'); ++ if (!trailer) ++ trailer = val + len - 1; ++ else ++ trailer--; ++ ++ while (*trailer && (*trailer == '"' || isblank(*trailer))) ++ *(trailer--) = '\0';; ++ ++ *res = key; ++ *value = val; ++ ++ return 1; ++} ++ + /* + * Read config env variables and check they have been set. + * +@@ -141,61 +189,30 @@ unsigned int defaults_read_config(void) + { + FILE *f; + char buf[MAX_LINE_LEN]; +- char *res, *value; ++ char *res; + + f = fopen(DEFAULTS_CONFIG_FILE, "r"); + if (!f) + return 0; + + while ((res = fgets(buf, MAX_LINE_LEN, f))) { +- char *trailer; +- int len; +- +- if (*res == '#' || !isalpha(*res)) +- continue; +- +- while (*res && *res == ' ') +- res++; +- +- if (!res) +- continue; ++ char *key, *value; + +- if (!(value = strchr(res, '='))) ++ if (!parse_line(res, &key, &value)) + continue; + +- *value++ = '\0'; +- +- while (*value && (*value == '"' || isblank(*value))) +- value++; +- +- len = strlen(value); +- +- if (value[len - 1] == '\n') { +- value[len - 1] = '\0'; +- len--; +- } +- +- trailer = strchr(value, '#'); +- if (!trailer) +- trailer = value + len - 1; +- else +- trailer--; +- +- while (*trailer && (*trailer == '"' || isblank(*trailer))) +- *(trailer--) = '\0';; +- +- if (check_set_config_value(res, ENV_NAME_MASTER_MAP, value) || +- check_set_config_value(res, ENV_NAME_TIMEOUT, value) || +- check_set_config_value(res, ENV_NAME_BROWSE_MODE, value) || +- check_set_config_value(res, ENV_NAME_LOGGING, value) || +- check_set_config_value(res, ENV_LDAP_SERVER, value) || +- check_set_config_value(res, ENV_NAME_MAP_OBJ_CLASS, value) || +- check_set_config_value(res, ENV_NAME_ENTRY_OBJ_CLASS, value) || +- check_set_config_value(res, ENV_NAME_MAP_ATTR, value) || +- check_set_config_value(res, ENV_NAME_ENTRY_ATTR, value) || +- check_set_config_value(res, ENV_NAME_VALUE_ATTR, value) || +- check_set_config_value(res, ENV_APPEND_OPTIONS, value) || +- check_set_config_value(res, ENV_AUTH_CONF_FILE, value)) ++ if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value) || ++ check_set_config_value(key, ENV_NAME_TIMEOUT, value) || ++ check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) || ++ check_set_config_value(key, ENV_NAME_LOGGING, value) || ++ check_set_config_value(key, ENV_LDAP_SERVER, value) || ++ check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) || ++ check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) || ++ check_set_config_value(key, ENV_NAME_MAP_ATTR, value) || ++ check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value) || ++ check_set_config_value(key, ENV_NAME_VALUE_ATTR, value) || ++ check_set_config_value(key, ENV_APPEND_OPTIONS, value) || ++ check_set_config_value(key, ENV_AUTH_CONF_FILE, value)) + ; + } + +@@ -336,6 +353,86 @@ struct ldap_schema *defaults_get_default_schema(void) + return schema; + } -diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2/modules/lookup_ldap.c ---- autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/modules/lookup_ldap.c 2007-11-20 14:09:58.000000000 +0900 -@@ -171,10 +171,207 @@ LDAP *init_ldap_connection(struct lookup ++static struct ldap_searchdn *alloc_searchdn(const char *value) ++{ ++ struct ldap_searchdn *sdn; ++ char *val; ++ ++ sdn = malloc(sizeof(struct ldap_searchdn)); ++ if (!sdn) ++ return NULL; ++ ++ val = strdup(value); ++ if (!val) { ++ free(sdn); ++ return NULL; ++ } ++ ++ sdn->basedn = val; ++ sdn->next = NULL; ++ ++ return sdn; ++} ++ ++void defaults_free_searchdns(struct ldap_searchdn *sdn) ++{ ++ struct ldap_searchdn *this = sdn; ++ struct ldap_searchdn *next; ++ ++ next = this; ++ while (this) { ++ next = this->next; ++ free(this->basedn); ++ free(this); ++ this = next; ++ } ++ ++ return; ++} ++ ++struct ldap_searchdn *defaults_get_searchdns(void) ++{ ++ FILE *f; ++ char buf[MAX_LINE_LEN]; ++ char *res; ++ struct ldap_searchdn *sdn, *last; ++ ++ f = fopen(DEFAULTS_CONFIG_FILE, "r"); ++ if (!f) ++ return NULL; ++ ++ sdn = last = NULL; ++ ++ while ((res = fgets(buf, MAX_LINE_LEN, f))) { ++ char *key, *value; ++ ++ if (!parse_line(res, &key, &value)) ++ continue; ++ ++ if (!strcasecmp(key, SEARCH_BASE)) { ++ struct ldap_searchdn *new = alloc_searchdn(value); ++ ++ if (!new) { ++ defaults_free_searchdns(sdn); ++ return NULL; ++ } ++ ++ if (!last) ++ last = new; ++ else { ++ last->next = new; ++ last = new; ++ } ++ ++ if (!sdn) ++ sdn = new; ++ } ++ } ++ ++ fclose(f); ++ return sdn; ++} ++ + struct ldap_schema *defaults_get_schema(void) + { + struct ldap_schema *schema; +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index ab5ab1e..0cb2f07 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -230,6 +230,11 @@ values must be set, any partial schema specification will be ignored. + .P + The configuration settings available are: + .TP ++.B SEARCH_BASE ++The base dn to use when searching for amap base dn. This entry may be ++given multiple times and each will be checked for a map base dn in ++the order they occur in the configuration. ++.TP + .B MAP_OBJECT_CLASS + The map object class. In the \fBnisMap\fP schema this corresponds to the class + \fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 9c18ca1..da52e71 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -171,10 +171,207 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) return ldap; } @@ -276,7 +507,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2 ldap = init_ldap_connection(ctxt); if (!ldap) -@@ -204,6 +401,61 @@ static LDAP *do_connect(struct lookup_co +@@ -204,6 +401,61 @@ static LDAP *do_connect(struct lookup_context *ctxt) return NULL; } @@ -338,7 +569,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2 return ldap; } -@@ -769,177 +1021,17 @@ static void free_context(struct lookup_c +@@ -769,175 +1021,17 @@ static void free_context(struct lookup_context *ctxt) ldap_memfree(ctxt->qdn); if (ctxt->server) free(ctxt->server); @@ -359,11 +590,10 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2 - char *query, *dn; - LDAPMessage *result, *e; - char *attrs[2]; -- struct berval **value; - int scope; - int rv, l; - -- attrs[0] = (char *) key; +- attrs[0] = LDAP_NO_ATTRS; - attrs[1] = NULL; - - if (!ctxt->mapname && !ctxt->base) { @@ -415,8 +645,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2 - } - - e = ldap_first_entry(ldap, result); -- if (e && (value = ldap_get_values_len(ldap, e, key))) { -- ldap_value_free_len(value); +- if (e) { - dn = ldap_get_dn(ldap, e); - debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); - ldap_msgfree(result); @@ -520,7 +749,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2 /* * This initializes a context (persistent non-global data) for queries to * this module. Return zero if we succeed. -@@ -996,31 +1088,6 @@ int lookup_init(const char *mapfmt, int +@@ -994,31 +1088,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co free_context(ctxt); return 1; } @@ -552,9 +781,29 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2 unbind_ldap_connection(ldap, ctxt); /* Open the parser, if we can. */ -diff -up autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list autofs-5.0.2/samples/autofs.conf.default.in ---- autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/samples/autofs.conf.default.in 2007-11-20 14:08:26.000000000 +0900 +diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in +index 85f4e34..2b1e20a 100644 +--- a/redhat/autofs.sysconfig.in ++++ b/redhat/autofs.sysconfig.in +@@ -21,6 +21,14 @@ BROWSE_MODE="no" + # + #LOGGING="none" + # ++# Define base dn for map dn lookup. ++# ++# SEARCH_BASE - base dn to use for searching for map search dn. ++# Multiple entries can be given and they are checked ++# in the order they occur here. ++# ++#SEARCH_BASE="" ++# + # Define the LDAP schema to used for lookups + # + # If no schema is set autofs will check each of the schemas +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index 85f4e34..2b1e20a 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in @@ -21,6 +21,14 @@ BROWSE_MODE="no" # #LOGGING="none" @@ -570,247 +819,3 @@ diff -up autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list aut # Define the LDAP schema to used for lookups # # If no schema is set autofs will check each of the schemas -diff -up autofs-5.0.2/lib/defaults.c.ldap-search-basedn-list autofs-5.0.2/lib/defaults.c ---- autofs-5.0.2/lib/defaults.c.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/lib/defaults.c 2007-11-20 14:08:26.000000000 +0900 -@@ -32,6 +32,8 @@ - - #define ENV_LDAP_SERVER "LDAP_SERVER" - -+#define SEARCH_BASE "SEARCH_BASE" -+ - #define ENV_NAME_MAP_OBJ_CLASS "MAP_OBJECT_CLASS" - #define ENV_NAME_ENTRY_OBJ_CLASS "ENTRY_OBJECT_CLASS" - #define ENV_NAME_MAP_ATTR "MAP_ATTRIBUTE" -@@ -130,6 +132,52 @@ static int check_set_config_value(const - return 0; - } - -+static int parse_line(char *line, char **res, char **value) -+{ -+ char *key, *val, *trailer; -+ int len; -+ -+ key = line; -+ -+ if (*key == '#' || !isalpha(*key)) -+ return 0; -+ -+ while (*key && *key == ' ') -+ key++; -+ -+ if (!key) -+ return 0; -+ -+ if (!(val = strchr(key, '='))) -+ return 0; -+ -+ *val++ = '\0'; -+ -+ while (*val && (*val == '"' || isblank(*val))) -+ val++; -+ -+ len = strlen(val); -+ -+ if (val[len - 1] == '\n') { -+ val[len - 1] = '\0'; -+ len--; -+ } -+ -+ trailer = strchr(val, '#'); -+ if (!trailer) -+ trailer = val + len - 1; -+ else -+ trailer--; -+ -+ while (*trailer && (*trailer == '"' || isblank(*trailer))) -+ *(trailer--) = '\0';; -+ -+ *res = key; -+ *value = val; -+ -+ return 1; -+} -+ - /* - * Read config env variables and check they have been set. - * -@@ -141,61 +189,30 @@ unsigned int defaults_read_config(void) - { - FILE *f; - char buf[MAX_LINE_LEN]; -- char *res, *value; -+ char *res; - - f = fopen(DEFAULTS_CONFIG_FILE, "r"); - if (!f) - return 0; - - while ((res = fgets(buf, MAX_LINE_LEN, f))) { -- char *trailer; -- int len; -- -- if (*res == '#' || !isalpha(*res)) -- continue; -- -- while (*res && *res == ' ') -- res++; -- -- if (!res) -- continue; -+ char *key, *value; - -- if (!(value = strchr(res, '='))) -+ if (!parse_line(res, &key, &value)) - continue; - -- *value++ = '\0'; -- -- while (*value && (*value == '"' || isblank(*value))) -- value++; -- -- len = strlen(value); -- -- if (value[len - 1] == '\n') { -- value[len - 1] = '\0'; -- len--; -- } -- -- trailer = strchr(value, '#'); -- if (!trailer) -- trailer = value + len - 1; -- else -- trailer--; -- -- while (*trailer && (*trailer == '"' || isblank(*trailer))) -- *(trailer--) = '\0';; -- -- if (check_set_config_value(res, ENV_NAME_MASTER_MAP, value) || -- check_set_config_value(res, ENV_NAME_TIMEOUT, value) || -- check_set_config_value(res, ENV_NAME_BROWSE_MODE, value) || -- check_set_config_value(res, ENV_NAME_LOGGING, value) || -- check_set_config_value(res, ENV_LDAP_SERVER, value) || -- check_set_config_value(res, ENV_NAME_MAP_OBJ_CLASS, value) || -- check_set_config_value(res, ENV_NAME_ENTRY_OBJ_CLASS, value) || -- check_set_config_value(res, ENV_NAME_MAP_ATTR, value) || -- check_set_config_value(res, ENV_NAME_ENTRY_ATTR, value) || -- check_set_config_value(res, ENV_NAME_VALUE_ATTR, value) || -- check_set_config_value(res, ENV_APPEND_OPTIONS, value) || -- check_set_config_value(res, ENV_AUTH_CONF_FILE, value)) -+ if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value) || -+ check_set_config_value(key, ENV_NAME_TIMEOUT, value) || -+ check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) || -+ check_set_config_value(key, ENV_NAME_LOGGING, value) || -+ check_set_config_value(key, ENV_LDAP_SERVER, value) || -+ check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) || -+ check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) || -+ check_set_config_value(key, ENV_NAME_MAP_ATTR, value) || -+ check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value) || -+ check_set_config_value(key, ENV_NAME_VALUE_ATTR, value) || -+ check_set_config_value(key, ENV_APPEND_OPTIONS, value) || -+ check_set_config_value(key, ENV_AUTH_CONF_FILE, value)) - ; - } - -@@ -336,6 +353,86 @@ struct ldap_schema *defaults_get_default - return schema; - } - -+static struct ldap_searchdn *alloc_searchdn(const char *value) -+{ -+ struct ldap_searchdn *sdn; -+ char *val; -+ -+ sdn = malloc(sizeof(struct ldap_searchdn)); -+ if (!sdn) -+ return NULL; -+ -+ val = strdup(value); -+ if (!val) { -+ free(sdn); -+ return NULL; -+ } -+ -+ sdn->basedn = val; -+ sdn->next = NULL; -+ -+ return sdn; -+} -+ -+void defaults_free_searchdns(struct ldap_searchdn *sdn) -+{ -+ struct ldap_searchdn *this = sdn; -+ struct ldap_searchdn *next; -+ -+ next = this; -+ while (this) { -+ next = this->next; -+ free(this->basedn); -+ free(this); -+ this = next; -+ } -+ -+ return; -+} -+ -+struct ldap_searchdn *defaults_get_searchdns(void) -+{ -+ FILE *f; -+ char buf[MAX_LINE_LEN]; -+ char *res; -+ struct ldap_searchdn *sdn, *last; -+ -+ f = fopen(DEFAULTS_CONFIG_FILE, "r"); -+ if (!f) -+ return NULL; -+ -+ sdn = last = NULL; -+ -+ while ((res = fgets(buf, MAX_LINE_LEN, f))) { -+ char *key, *value; -+ -+ if (!parse_line(res, &key, &value)) -+ continue; -+ -+ if (!strcasecmp(key, SEARCH_BASE)) { -+ struct ldap_searchdn *new = alloc_searchdn(value); -+ -+ if (!new) { -+ defaults_free_searchdns(sdn); -+ return NULL; -+ } -+ -+ if (!last) -+ last = new; -+ else { -+ last->next = new; -+ last = new; -+ } -+ -+ if (!sdn) -+ sdn = new; -+ } -+ } -+ -+ fclose(f); -+ return sdn; -+} -+ - struct ldap_schema *defaults_get_schema(void) - { - struct ldap_schema *schema; -diff -up autofs-5.0.2/man/auto.master.5.in.ldap-search-basedn-list autofs-5.0.2/man/auto.master.5.in ---- autofs-5.0.2/man/auto.master.5.in.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 -+++ autofs-5.0.2/man/auto.master.5.in 2007-11-20 14:08:26.000000000 +0900 -@@ -224,6 +224,11 @@ values must be set, any partial schema s - .P - The configuration settings available are: - .TP -+.B SEARCH_BASE -+The base dn to use when searching for amap base dn. This entry may be -+given multiple times and each will be checked for a map base dn in -+the order they occur in the configuration. -+.TP - .B MAP_OBJECT_CLASS - The map object class. In the \fBnisMap\fP schema this corresponds to the class - \fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class diff --git a/autofs-5.0.2-percent-hack-fix.patch b/autofs-5.0.2-percent-hack-fix.patch new file mode 100644 index 0000000..f4f5023 --- /dev/null +++ b/autofs-5.0.2-percent-hack-fix.patch @@ -0,0 +1,300 @@ +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 13fbff7..65f1fda 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -1411,6 +1411,140 @@ next: + return NSS_STATUS_SUCCESS; + } + ++/* ++ * Deal with encode and decode of % hack. ++ * Return ++ * 0 => % hack not present. ++ * -1 => syntax error or alloc fail. ++ * 1 transofrmed value returned. ++ */ ++static int decode_percent_hack(const char *name, char **key) ++{ ++ const char *tmp; ++ char *ptr, *new; ++ ++ if (!key) ++ return -1; ++ ++ *key = NULL; ++ ++ tmp = name; ++ while (*tmp && *tmp != '%' && *tmp != '[' && *tmp != ']') ++ tmp++; ++ if (!*tmp) ++ return 0; ++ ++ tmp = name; ++ while (*tmp) { ++ if (*tmp == '%') { ++ tmp++; ++ if (!*tmp) ++ return -1; ++ if (*tmp != '[') ++ continue; ++ tmp++; ++ while (*tmp && *tmp != ']') { ++ if (*tmp == '%') ++ tmp++; ++ tmp++; ++ } ++ if (!tmp) ++ return -1; ++ } ++ tmp++; ++ } ++ ++ new = malloc(strlen(name) + 1); ++ if (!new) ++ return -1; ++ ++ ptr = new; ++ tmp = name; ++ while (*tmp) { ++ if (*tmp == '%' || *tmp == '[' || *tmp == ']') { ++ tmp++; ++ if (*tmp && *tmp != '%') ++ continue; ++ } ++ *ptr++ = *tmp++; ++ } ++ *ptr = '\0'; ++ ++ *key = new; ++ ++ return strlen(new); ++} ++ ++static int encode_percent_hack(const char *name, char **key, unsigned int use_class) ++{ ++ const char *tmp; ++ unsigned int len = 0; ++ char *ptr, *new; ++ ++ if (!key) ++ return -1; ++ ++ *key = NULL; ++ ++ tmp = name; ++ while (*tmp) { ++ if (*tmp == '%') ++ len++; ++ else if (isupper(*tmp)) { ++ tmp++; ++ len++; ++ if (!use_class) ++ len++; ++ else { ++ if (*tmp && isupper(*tmp)) ++ len += 2; ++ else ++ return 0; ++ while (*tmp && isupper(*tmp)) { ++ len++; ++ tmp++; ++ } ++ } ++ continue; ++ } ++ len++; ++ tmp++; ++ } ++ if (len == strlen(name)) ++ return 0; ++ ++ new = malloc(len + 1); ++ if (!new) ++ return -1; ++ ++ ptr = new; ++ tmp = name; ++ while (*tmp) { ++ if (*tmp == '%') ++ *ptr++ = '%'; ++ else if (isupper(*tmp)) { ++ char next = *tmp++; ++ *ptr++ = '%'; ++ if (*tmp && (!isupper(*tmp) || !use_class)) ++ *ptr++ = next; ++ else { ++ *ptr++ = '['; ++ *ptr++ = next; ++ while (*tmp && isupper(*tmp)) ++ *ptr++ = *tmp++; ++ *ptr++ = ']'; ++ } ++ continue; ++ } ++ *ptr++ = *tmp++; ++ } ++ *ptr = '\0'; ++ ++ *key = new; ++ ++ return strlen(new); ++} ++ + static int read_one_map(struct autofs_point *ap, + struct lookup_context *ctxt, + time_t age, int *result_ldap) +@@ -1518,7 +1652,7 @@ static int read_one_map(struct autofs_point *ap, + * people using older schemas that allow '*' as a key + * value. Another case where there can be multiple key + * values is when people have used the "%" hack to specify +- * case matching ctriteria in a caase insensitive attribute. ++ * case matching ctriteria in a case insensitive attribute. + */ + count = ldap_count_values_len(bvKey); + if (count > 1) { +@@ -1647,9 +1781,30 @@ static int read_one_map(struct autofs_point *ap, + *k_val = '*'; + } + +- s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt); +- if (!s_key) +- goto next; ++ if (strcasecmp(class, "nisObject")) { ++ s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt); ++ if (!s_key) ++ goto next; ++ } else { ++ char *dec_key; ++ int dec_len = decode_percent_hack(k_val, &dec_key); ++ ++ if (dec_len < 0) { ++ crit(ap->logopt, ++ "could not use percent hack to decode key %s", ++ k_val); ++ goto next; ++ } ++ ++ if (dec_len == 0) ++ s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt); ++ else { ++ s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt); ++ free(dec_key); ++ } ++ if (!s_key) ++ goto next; ++ } + + cache_writelock(mc); + cache_update(mc, source, s_key, mapent, age); +@@ -1712,6 +1867,8 @@ static int lookup_one(struct autofs_point *ap, + char *query; + LDAPMessage *result, *e; + char *class, *info, *entry; ++ char *enc_key1, *enc_key2; ++ int enc_len1 = 0, enc_len2 = 0; + struct berval **bvKey; + struct berval **bvValues; + char *attrs[3]; +@@ -1742,14 +1899,38 @@ static int lookup_one(struct autofs_point *ap, + + if (*qKey == '*' && qKey_len == 1) + *qKey = '/'; ++ else if (!strcasecmp(class, "nisObject")) { ++ enc_len1 = encode_percent_hack(qKey, &enc_key1, 0); ++ if (enc_len1 < 0) { ++ crit(ap->logopt, ++ "could not use percent hack encode key %s", ++ qKey); ++ return CHE_FAIL; ++ } ++ if (enc_len1 != 0) { ++ enc_len2 = encode_percent_hack(qKey, &enc_key2, 1); ++ if (enc_len2 < 0) { ++ crit(ap->logopt, ++ "could not use percent hack encode key %s", ++ qKey); ++ return CHE_FAIL; ++ } ++ } ++ } + + /* Build a query string. */ + l = strlen(class) + 3*strlen(entry) + strlen(qKey) + 35; ++ if (enc_len1) ++ l += 2*strlen(entry) + enc_len1 + enc_len2 + 6; + + query = alloca(l); + if (query == NULL) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(ap->logopt, MODPREFIX "malloc: %s", estr); ++ if (enc_len1) { ++ free(enc_key1); ++ free(enc_key2); ++ } + return CHE_FAIL; + } + +@@ -1757,8 +1938,27 @@ static int lookup_one(struct autofs_point *ap, + * Look for an entry in class under ctxt-base + * whose entry is equal to qKey. + */ +- ql = sprintf(query, +- "(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))", class, entry, qKey, entry, entry); ++ if (!enc_len1) { ++ ql = sprintf(query, ++ "(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))", ++ class, entry, qKey, entry, entry); ++ } else { ++ if (enc_len2) { ++ ql = sprintf(query, ++ "(&(objectclass=%s)" ++ "(|(%s=%s)(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))", ++ class, entry, qKey, ++ entry, enc_key1, entry, enc_key2, entry, entry); ++ free(enc_key1); ++ free(enc_key2); ++ } else { ++ ql = sprintf(query, ++ "(&(objectclass=%s)" ++ "(|(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))", ++ class, entry, qKey, entry, enc_key1, entry, entry); ++ free(enc_key1); ++ } ++ } + if (ql >= l) { + error(ap->logopt, + MODPREFIX "error forming query string"); +@@ -1934,9 +2134,30 @@ static int lookup_one(struct autofs_point *ap, + goto next; + } + +- s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt); +- if (!s_key) +- goto next; ++ if (strcasecmp(class, "nisObject")) { ++ s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt); ++ if (!s_key) ++ goto next; ++ } else { ++ char *dec_key; ++ int dec_len = decode_percent_hack(k_val, &dec_key); ++ ++ if (dec_len < 0) { ++ crit(ap->logopt, ++ "could not use percent hack to decode key %s", ++ k_val); ++ goto next; ++ } ++ ++ if (dec_len == 0) ++ s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt); ++ else { ++ s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt); ++ free(dec_key); ++ } ++ if (!s_key) ++ goto next; ++ } + + cache_writelock(mc); + ret = cache_update(mc, source, s_key, mapent, age); diff --git a/autofs-5.0.2-quell-mount-module-message.patch b/autofs-5.0.2-quell-mount-module-message.patch new file mode 100644 index 0000000..ef6abef --- /dev/null +++ b/autofs-5.0.2-quell-mount-module-message.patch @@ -0,0 +1,27 @@ +diff --git a/daemon/mount.c b/daemon/mount.c +index 59f8f44..494ede1 100644 +--- a/daemon/mount.c ++++ b/daemon/mount.c +@@ -38,14 +38,21 @@ int do_mount(struct autofs_point *ap, const char *root, const char *name, int na + char **ngp; + int rv; + +- mod = open_mount(modstr = fstype, ERR_PREFIX); ++ /* Initially look for a mount module but don't issue an error on fail */ ++ mod = open_mount(modstr = fstype, NULL); + if (!mod) { + for (ngp = not_generic; *ngp; ngp++) { + if (!strcmp(fstype, *ngp)) + break; + } ++ /* ++ * If there's not a known mount module use the generic module, ++ * otherwise redo the fs mount module with error reporting ++ */ + if (!*ngp) + mod = open_mount(modstr = "generic", ERR_PREFIX); ++ else ++ mod = open_mount(modstr = fstype, ERR_PREFIX); + if (!mod) { + error(ap->logopt, + "cannot find mount method for filesystem %s", diff --git a/autofs-5.0.2-quote-exports-fix.patch b/autofs-5.0.2-quote-exports-fix.patch new file mode 100644 index 0000000..f23683a --- /dev/null +++ b/autofs-5.0.2-quote-exports-fix.patch @@ -0,0 +1,69 @@ +diff -up autofs-5.0.1/modules/parse_sun.c.quote-exports-fix autofs-5.0.1/modules/parse_sun.c +--- autofs-5.0.1/modules/parse_sun.c.quote-exports-fix 2007-12-15 13:23:45.000000000 +0900 ++++ autofs-5.0.1/modules/parse_sun.c 2007-12-15 13:24:20.000000000 +0900 +@@ -873,7 +873,7 @@ static int parse_mapent(const char *ent, + } + + if (!validate_location(loc)) { +- warn(logopt, MODPREFIX "invalid location"); ++ warn(logopt, MODPREFIX "invalid location %s", loc); + free(myoptions); + free(loc); + return 0; +@@ -1338,6 +1338,23 @@ int parse_mount(struct autofs_point *ap, + int loclen; + int l; + ++ /* ++ * If this is an offset belonging to a multi-mount entry ++ * it's already been parsed (above) and any option string ++ * has already been stripped so just use the remainder. ++ */ ++ if (*name == '/' && ++ (me = cache_lookup_distinct(mc, name)) && me->multi) { ++ loc = strdup(p); ++ if (!loc) { ++ free(options); ++ warn(ap->logopt, MODPREFIX "out of memory"); ++ return 1; ++ } ++ loclen = strlen(p); ++ goto mount_it; ++ } ++ + l = chunklen(p, check_colon(p)); + loc = dequote(p, l, ap->logopt); + if (!loc) { +@@ -1355,9 +1372,9 @@ int parse_mount(struct autofs_point *ap, + } + + if (!validate_location(loc)) { ++ warn(ap->logopt, MODPREFIX "invalid location %s", loc); + free(loc); + free(options); +- warn(ap->logopt, MODPREFIX "invalid location"); + return 1; + } + +@@ -1381,10 +1398,11 @@ int parse_mount(struct autofs_point *ap, + } + + if (!validate_location(ent)) { ++ warn(ap->logopt, ++ MODPREFIX "invalid location %s", loc); + free(ent); + free(loc); + free(options); +- warn(ap->logopt, MODPREFIX "invalid location"); + return 1; + } + +@@ -1418,7 +1436,7 @@ int parse_mount(struct autofs_point *ap, + MODPREFIX "entry %s is empty!", name); + return 1; + } +- ++mount_it: + debug(ap->logopt, + MODPREFIX "core of entry: options=%s, loc=%.*s", + options, loclen, loc); diff --git a/autofs-5.0.2-random-selection-fix.patch b/autofs-5.0.2-random-selection-fix.patch index 2b40d06..da0bac9 100644 --- a/autofs-5.0.2-random-selection-fix.patch +++ b/autofs-5.0.2-random-selection-fix.patch @@ -1,18 +1,42 @@ -diff -up autofs-5.0.2/include/replicated.h.random-selection-fix autofs-5.0.2/include/replicated.h ---- autofs-5.0.2/include/replicated.h.random-selection-fix 2007-06-18 15:18:08.000000000 +0800 -+++ autofs-5.0.2/include/replicated.h 2007-11-20 14:55:28.000000000 +0900 -@@ -63,7 +63,7 @@ struct host { - void seed_random(void); - void free_host_list(struct host **); - int parse_location(struct host **, const char *); --int prune_host_list(struct host **, unsigned int, const char *); -+int prune_host_list(struct host **, unsigned int, const char *, unsigned int); - void dump_host_list(struct host *); +diff --git a/daemon/automount.c b/daemon/automount.c +index 7b79f02..4b6584a 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -49,9 +49,9 @@ const char *confdir = AUTOFS_CONF_DIR; /* Location of autofs config file */ - #endif -diff -up autofs-5.0.2/include/automount.h.random-selection-fix autofs-5.0.2/include/automount.h ---- autofs-5.0.2/include/automount.h.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/include/automount.h 2007-11-20 14:55:28.000000000 +0900 + const char *global_options; /* Global option, from command line */ + +-static char *pid_file = NULL; /* File in which to keep pid */ +-unsigned int random_selection; /* use random policy when selecting +- * which multi-mount host to mount */ ++static char *pid_file = NULL; /* File in which to keep pid */ ++unsigned int global_random_selection; /* use random policy when selecting ++ * which multi-mount host to mount */ + static int start_pipefd[2]; + static int st_stat = 0; + static int *pst_stat = &st_stat; +@@ -1490,7 +1490,7 @@ int main(int argc, char *argv[]) + timeout = defaults_get_timeout(); + ghost = defaults_get_browse_mode(); + logging = defaults_get_logging(); +- random_selection = 0; ++ global_random_selection = 0; + global_options = NULL; + have_global_options = 0; + foreground = 0; +@@ -1531,7 +1531,7 @@ int main(int argc, char *argv[]) + exit(0); + + case 'r': +- random_selection = 1; ++ global_random_selection = 1; + break; + + case 'O': +diff --git a/include/automount.h b/include/automount.h +index d9e4ecd..d55ba5c 100644 +--- a/include/automount.h ++++ b/include/automount.h @@ -448,6 +448,8 @@ struct autofs_point { enum states state; /* Current state */ int state_pipe[2]; /* State change router pipe */ @@ -22,10 +46,107 @@ diff -up autofs-5.0.2/include/automount.h.random-selection-fix autofs-5.0.2/incl struct autofs_point *parent; /* Owner of mounts list for submount */ pthread_mutex_t mounts_mutex; /* Protect mount lists */ pthread_cond_t mounts_cond; /* Submounts condition variable */ -diff -up autofs-5.0.2/modules/mount_nfs.c.random-selection-fix autofs-5.0.2/modules/mount_nfs.c ---- autofs-5.0.2/modules/mount_nfs.c.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/modules/mount_nfs.c 2007-11-20 14:55:28.000000000 +0900 -@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, +diff --git a/include/replicated.h b/include/replicated.h +index c77cda6..3afe9f7 100644 +--- a/include/replicated.h ++++ b/include/replicated.h +@@ -63,7 +63,7 @@ struct host { + void seed_random(void); + void free_host_list(struct host **); + int parse_location(struct host **, const char *); +-int prune_host_list(struct host **, unsigned int, const char *); ++int prune_host_list(struct host **, unsigned int, const char *, unsigned int); + void dump_host_list(struct host *); + + #endif +diff --git a/lib/master_parse.y b/lib/master_parse.y +index ab2895d..70b48be 100644 +--- a/lib/master_parse.y ++++ b/lib/master_parse.y +@@ -56,6 +56,8 @@ static char *type; + static char *format; + static long timeout; + static unsigned ghost; ++extern unsigned global_random_selection; ++static unsigned random_selection; + static char **tmp_argv; + static int tmp_argc; + static char **local_argv; +@@ -93,7 +95,7 @@ static int master_fprintf(FILE *, char *, ...); + + %token COMMENT + %token MAP +-%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG ++%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM + %token COLON COMMA NL DDASH + %type map + %type options +@@ -174,6 +176,7 @@ line: + | PATH COLON { master_notify($1); YYABORT; } + | PATH OPTION { master_notify($2); YYABORT; } + | PATH NILL { master_notify($2); YYABORT; } ++ | PATH OPT_RANDOM { master_notify($1); YYABORT; } + | PATH OPT_DEBUG { master_notify($1); YYABORT; } + | PATH OPT_TIMEOUT { master_notify($1); YYABORT; } + | PATH OPT_GHOST { master_notify($1); YYABORT; } +@@ -543,6 +546,7 @@ daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; } + | OPT_GHOST { ghost = 1; } + | OPT_VERBOSE { verbose = 1; } + | OPT_DEBUG { debug = 1; } ++ | OPT_RANDOM { random_selection = 1; } + ; + + mount_option: OPTION +@@ -600,6 +604,7 @@ static void local_init_vars(void) + debug = 0; + timeout = -1; + ghost = defaults_get_browse_mode(); ++ random_selection = global_random_selection; + tmp_argv = NULL; + tmp_argc = 0; + local_argv = NULL; +@@ -790,6 +795,7 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + } + set_mnt_logging(ap); + } ++ entry->ap->random_selection = random_selection; + + /* + source = master_find_map_source(entry, type, format, +diff --git a/lib/master_tok.l b/lib/master_tok.l +index ff69a24..013a15a 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -324,6 +324,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) + -g|--ghost|-?browse { return(OPT_GHOST); } + -v|--verbose { return(OPT_VERBOSE); } + -d|--debug { return(OPT_DEBUG); } ++ -r|--random-multimount-selection { return(OPT_RANDOM); } + + {OPTWS}","{OPTWS} { return(COMMA); } + +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index 249c9a7..ab5ab1e 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -146,6 +146,12 @@ to prevent symlinking of local NFS mounts. Nowadays it can be used to + prevent bind mounting of local NFS filesystems as well. If you need to + prevent bind mounting for only specific entrys in a map then this + can be done by adding the "port=" mount option to the given entries. ++.TP ++.I "\-r, \-\-random-multimount-selection" ++Enables the use of ramdom selection when choosing a host from a ++list of replicated servers. This option is applied to this mount ++only, overriding the global setting that may be specified on the ++command line. + .SH GENERAL SYSTEM DEFAULTS CONFIGURATION + .P + The default value of several general settings may be changed in the +diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c +index e7a9a8a..e4480c5 100644 +--- a/modules/mount_nfs.c ++++ b/modules/mount_nfs.c +@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int warn(ap->logopt, MODPREFIX "no hosts available"); return 1; } @@ -34,9 +155,10 @@ diff -up autofs-5.0.2/modules/mount_nfs.c.random-selection-fix autofs-5.0.2/modu if (!hosts) { warn(ap->logopt, MODPREFIX "no hosts available"); -diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/modules/replicated.c ---- autofs-5.0.2/modules/replicated.c.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/modules/replicated.c 2007-11-20 14:55:28.000000000 +0900 +diff --git a/modules/replicated.c b/modules/replicated.c +index 0764d4a..e15587c 100644 +--- a/modules/replicated.c ++++ b/modules/replicated.c @@ -74,8 +74,6 @@ #define max(x, y) (x >= y ? x : y) #define mmax(x, y, z) (max(x, y) == x ? max(x, z) : max(y, z)) @@ -46,7 +168,7 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod void seed_random(void) { int fd; -@@ -392,7 +390,7 @@ static unsigned short get_port_option(co +@@ -392,7 +390,7 @@ static unsigned short get_port_option(const char *options) static unsigned int get_nfs_info(struct host *host, struct conn_info *pm_info, struct conn_info *rpc_info, const char *proto, unsigned int version, @@ -66,7 +188,7 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod { struct conn_info pm_info, rpc_info; time_t timeout = RPC_TIMEOUT; -@@ -559,7 +559,9 @@ static int get_vers_and_cost(struct host +@@ -559,7 +559,9 @@ static int get_vers_and_cost(struct host *host, unsigned int version, const char vers &= version; if (version & UDP_REQUESTED) { @@ -77,7 +199,7 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod if (supported) { ret = 1; host->version |= (supported << 8); -@@ -567,7 +569,9 @@ static int get_vers_and_cost(struct host +@@ -567,7 +569,9 @@ static int get_vers_and_cost(struct host *host, unsigned int version, const char } if (version & TCP_REQUESTED) { @@ -88,7 +210,7 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod if (supported) { ret = 1; host->version |= supported; -@@ -577,7 +581,9 @@ static int get_vers_and_cost(struct host +@@ -577,7 +581,9 @@ static int get_vers_and_cost(struct host *host, unsigned int version, const char return ret; } @@ -110,7 +232,7 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod { struct host *this, *last, *first; struct host *new = NULL; -@@ -734,7 +742,8 @@ int prune_host_list(struct host **list, +@@ -734,7 +742,8 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) break; if (this->name) { @@ -120,7 +242,7 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod if (!status) { if (this == first) { first = next; -@@ -824,7 +833,9 @@ int prune_host_list(struct host **list, +@@ -824,7 +833,9 @@ int prune_host_list(struct host **list, unsigned int vers, const char *options) remove_host(list, this); add_host(&new, this); } else { @@ -131,117 +253,3 @@ diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/mod if (status) { this->version = selected_version; remove_host(list, this); -diff -up autofs-5.0.2/daemon/automount.c.random-selection-fix autofs-5.0.2/daemon/automount.c ---- autofs-5.0.2/daemon/automount.c.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/daemon/automount.c 2007-11-20 14:55:28.000000000 +0900 -@@ -52,9 +52,9 @@ const char *confdir = AUTOFS_CONF_DIR; / - - const char *global_options; /* Global option, from command line */ - --static char *pid_file = NULL; /* File in which to keep pid */ --unsigned int random_selection; /* use random policy when selecting -- * which multi-mount host to mount */ -+static char *pid_file = NULL; /* File in which to keep pid */ -+unsigned int global_random_selection; /* use random policy when selecting -+ * which multi-mount host to mount */ - static int start_pipefd[2]; - static int st_stat = 0; - static int *pst_stat = &st_stat; -@@ -1469,7 +1469,7 @@ int main(int argc, char *argv[]) - timeout = defaults_get_timeout(); - ghost = defaults_get_browse_mode(); - logging = defaults_get_logging(); -- random_selection = 0; -+ global_random_selection = 0; - global_options = NULL; - have_global_options = 0; - foreground = 0; -@@ -1510,7 +1510,7 @@ int main(int argc, char *argv[]) - exit(0); - - case 'r': -- random_selection = 1; -+ global_random_selection = 1; - break; - - case 'O': -diff -up autofs-5.0.2/lib/master_tok.l.random-selection-fix autofs-5.0.2/lib/master_tok.l ---- autofs-5.0.2/lib/master_tok.l.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/lib/master_tok.l 2007-11-20 14:55:28.000000000 +0900 -@@ -324,6 +324,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|-- - -g|--ghost|-?browse { return(OPT_GHOST); } - -v|--verbose { return(OPT_VERBOSE); } - -d|--debug { return(OPT_DEBUG); } -+ -r|--random-multimount-selection { return(OPT_RANDOM); } - - {OPTWS}","{OPTWS} { return(COMMA); } - -diff -up autofs-5.0.2/lib/master_parse.y.random-selection-fix autofs-5.0.2/lib/master_parse.y ---- autofs-5.0.2/lib/master_parse.y.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/lib/master_parse.y 2007-11-20 14:55:28.000000000 +0900 -@@ -56,6 +56,8 @@ static char *type; - static char *format; - static long timeout; - static unsigned ghost; -+extern unsigned global_random_selection; -+static unsigned random_selection; - static char **tmp_argv; - static int tmp_argc; - static char **local_argv; -@@ -93,7 +95,7 @@ static int master_fprintf(FILE *, char * - - %token COMMENT - %token MAP --%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG -+%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM - %token COLON COMMA NL DDASH - %type map - %type options -@@ -174,6 +176,7 @@ line: - | PATH COLON { master_notify($1); YYABORT; } - | PATH OPTION { master_notify($2); YYABORT; } - | PATH NILL { master_notify($2); YYABORT; } -+ | PATH OPT_RANDOM { master_notify($1); YYABORT; } - | PATH OPT_DEBUG { master_notify($1); YYABORT; } - | PATH OPT_TIMEOUT { master_notify($1); YYABORT; } - | PATH OPT_GHOST { master_notify($1); YYABORT; } -@@ -543,6 +546,7 @@ daemon_option: OPT_TIMEOUT NUMBER { time - | OPT_GHOST { ghost = 1; } - | OPT_VERBOSE { verbose = 1; } - | OPT_DEBUG { debug = 1; } -+ | OPT_RANDOM { random_selection = 1; } - ; - - mount_option: OPTION -@@ -600,6 +604,7 @@ static void local_init_vars(void) - debug = 0; - timeout = -1; - ghost = defaults_get_browse_mode(); -+ random_selection = global_random_selection; - tmp_argv = NULL; - tmp_argc = 0; - local_argv = NULL; -@@ -790,6 +795,7 @@ int master_parse_entry(const char *buffe - } - set_mnt_logging(ap); - } -+ entry->ap->random_selection = random_selection; - - /* - source = master_find_map_source(entry, type, format, -diff -up autofs-5.0.2/man/auto.master.5.in.random-selection-fix autofs-5.0.2/man/auto.master.5.in ---- autofs-5.0.2/man/auto.master.5.in.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 -+++ autofs-5.0.2/man/auto.master.5.in 2007-11-20 14:55:28.000000000 +0900 -@@ -146,6 +146,12 @@ to prevent symlinking of local NFS mount - prevent bind mounting of local NFS filesystems as well. If you need to - prevent bind mounting for only specific entrys in a map then this - can be done by adding the "port=" mount option to the given entries. -+.TP -+.I "\-r, \-\-random-multimount-selection" -+Enables the use of ramdom selection when choosing a host from a -+list of replicated servers. This option is applied to this mount -+only, overriding the global setting that may be specified on the -+command line. - .SH GENERAL SYSTEM DEFAULTS CONFIGURATION - .P - The default value of several general settings may be changed in the diff --git a/autofs-5.0.2-remove-unsed-export-validation-code.patch b/autofs-5.0.2-remove-unsed-export-validation-code.patch new file mode 100644 index 0000000..8b89e6b --- /dev/null +++ b/autofs-5.0.2-remove-unsed-export-validation-code.patch @@ -0,0 +1,611 @@ +diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c +index 831d456..d79a94f 100644 +--- a/lib/rpc_subs.c ++++ b/lib/rpc_subs.c +@@ -52,10 +52,7 @@ + /* Get numeric value of the n bits starting at position p */ + #define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) + +-static char *domain = NULL; +- + inline void dump_core(void); +-static pthread_mutex_t networks_mutex = PTHREAD_MUTEX_INITIALIZER; + + /* + * Create a UDP RPC client +@@ -764,573 +761,6 @@ void rpc_exports_free(exports list) + return; + } + +-static int masked_match(const char *addr, const char *mask) +-{ +- char buf[MAX_IFC_BUF], *ptr; +- struct sockaddr_in saddr; +- struct sockaddr_in6 saddr6; +- struct ifconf ifc; +- struct ifreq *ifr; +- int sock, cl_flags, ret, i, is_ipv4, is_ipv6; +- unsigned int msize; +- +- sock = socket(AF_INET, SOCK_DGRAM, 0); +- if (sock < 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "socket creation failed: %s", estr); +- return 0; +- } +- +- if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(sock, F_SETFD, cl_flags); +- } +- +- ifc.ifc_len = sizeof(buf); +- ifc.ifc_req = (struct ifreq *) buf; +- ret = ioctl(sock, SIOCGIFCONF, &ifc); +- if (ret == -1) { +- close(sock); +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "ioctl: %s", estr); +- return 0; +- } +- +- is_ipv4 = is_ipv6 = 0; +- is_ipv4 = inet_pton(AF_INET, addr, &saddr.sin_addr); +- if (!is_ipv4) +- is_ipv6 = inet_pton(AF_INET6, addr, &saddr6.sin6_addr); +- +- if (strchr(mask, '.')) { +- struct sockaddr_in maddr; +- uint32_t ma; +- int i = 0; +- +- ret = inet_aton(mask, &maddr.sin_addr); +- if (!ret) { +- close(sock); +- return 0; +- } +- +- ma = ntohl((uint32_t) maddr.sin_addr.s_addr); +- while (!(ma & 1)) { +- i++; +- ma = ma >> 1; +- } +- +- msize = i; +- } else +- msize = atoi(mask); +- +- i = 0; +- ptr = (char *) &ifc.ifc_buf[0]; +- +- while (ptr < buf + ifc.ifc_len) { +- ifr = (struct ifreq *) ptr; +- +- switch (ifr->ifr_addr.sa_family) { +- case AF_INET: +- { +- struct sockaddr_in *if_addr; +- uint32_t m, ia, ha; +- +- if (!is_ipv4 || msize > 32) +- break; +- +- m = -1; +- m = m << (32 - msize); +- ha = ntohl((uint32_t) saddr.sin_addr.s_addr); +- +- if_addr = (struct sockaddr_in *) &ifr->ifr_addr; +- ia = ntohl((uint32_t) if_addr->sin_addr.s_addr); +- +- if ((ia & m) == (ha & m)) { +- close(sock); +- return 1; +- } +- break; +- } +- +- /* glibc rpc only understands IPv4 atm */ +- case AF_INET6: +- break; +- +- default: +- break; +- } +- +- i++; +- ptr = (char *) &ifc.ifc_req[i]; +- } +- +- close(sock); +- return 0; +-} +- +-/* +- * This function has been adapted from the match_patern function +- * found in OpenSSH and is used in accordance with the copyright +- * notice found their. +- * +- * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland. +- */ +-/* +- * Returns true if the given string matches the pattern (which +- * may contain ? and * as wildcards), and zero if it does not +- * match. +- */ +-static int pattern_match(const char *s, const char *pattern) +-{ +- for (;;) { +- /* If at end of pattern, accept if also at end of string. */ +- if (!*pattern) +- return !*s; +- +- if (*pattern == '*') { +- /* Skip the asterisk. */ +- pattern++; +- +- /* If at end of pattern, accept immediately. */ +- if (!*pattern) +- return 1; +- +- /* If next character in pattern is known, optimize. */ +- if (*pattern != '?' && *pattern != '*') { +- /* +- * Look instances of the next character in +- * pattern, and try to match starting from +- * those. +- */ +- for (; *s; s++) +- if (*s == *pattern && +- pattern_match(s + 1, pattern + 1)) +- return 1; +- +- /* Failed. */ +- return 0; +- } +- /* +- * Move ahead one character at a time and try to +- * match at each position. +- */ +- for (; *s; s++) +- if (pattern_match(s, pattern)) +- return 1; +- /* Failed. */ +- return 0; +- } +- /* +- * There must be at least one more character in the string. +- * If we are at the end, fail. +- */ +- if (!*s) +- return 0; +- +- /* Check if the next character of the string is acceptable. */ +- if (*pattern != '?' && *pattern != *s) +- return 0; +- +- /* Move to the next character, both in string and in pattern. */ +- s++; +- pattern++; +- } +- /* NOTREACHED */ +-} +- +-static int name_match(const char *name, const char *pattern) +-{ +- int ret; +- +- if (strchr(pattern, '*') || strchr(pattern, '?')) +- ret = pattern_match(name, pattern); +- else { +- ret = !memcmp(name, pattern, strlen(pattern)); +- /* Name could still be a netgroup (Solaris) */ +- if (!ret) +- ret = innetgr(pattern, name, NULL, domain); +- } +- +- return ret; +-} +- +-static int fqdn_match(const char *pattern) +-{ +- char buf[MAX_IFC_BUF], *ptr; +- struct ifconf ifc; +- struct ifreq *ifr; +- int sock, cl_flags, ret, i; +- char fqdn[NI_MAXHOST + 1]; +- +- sock = socket(AF_INET, SOCK_DGRAM, 0); +- if (sock < 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "socket creation failed: %s", estr); +- return 0; +- } +- +- if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(sock, F_SETFD, cl_flags); +- } +- +- ifc.ifc_len = sizeof(buf); +- ifc.ifc_req = (struct ifreq *) buf; +- ret = ioctl(sock, SIOCGIFCONF, &ifc); +- if (ret == -1) { +- close(sock); +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "ioctl: %s", estr); +- return 0; +- } +- +- i = 0; +- ptr = (char *) &ifc.ifc_buf[0]; +- +- while (ptr < buf + ifc.ifc_len) { +- ifr = (struct ifreq *) ptr; +- +- switch (ifr->ifr_addr.sa_family) { +- case AF_INET: +- { +- socklen_t slen = sizeof(struct sockaddr); +- +- ret = getnameinfo(&ifr->ifr_addr, slen, fqdn, +- NI_MAXHOST, NULL, 0, NI_NAMEREQD); +- if (!ret) { +- ret = name_match(fqdn, pattern); +- if (ret) { +- close(sock); +- return 1; +- } +- } +- break; +- } +- +- /* glibc rpc only understands IPv4 atm */ +- case AF_INET6: +- break; +- +- default: +- break; +- } +- +- i++; +- ptr = (char *) &ifc.ifc_req[i]; +- } +- +- close(sock); +- return 0; +-} +- +-static int string_match(const char *myname, const char *pattern) +-{ +- struct addrinfo hints, *ni; +- int ret; +- +- /* Try simple name match first */ +- ret = name_match(myname, pattern); +- if (ret) +- goto done; +- +- memset(&hints, 0, sizeof(hints)); +- hints.ai_flags = AI_CANONNAME; +- hints.ai_family = 0; +- hints.ai_socktype = 0; +- +- /* See if our canonical name matches */ +- if (getaddrinfo(myname, NULL, &hints, &ni) == 0) { +- ret = name_match(ni->ai_canonname, pattern); +- freeaddrinfo(ni); +- } else +- warn(LOGOPT_ANY, "name lookup failed: %s", gai_strerror(ret)); +- if (ret) +- goto done; +- +- /* Lastly see if the name of an interfaces matches */ +- ret = fqdn_match(pattern); +-done: +- return ret; +-} +- +-static unsigned int inet_get_net_len(uint32_t net) +-{ +- int i; +- +- for (i = 0; i < 32; i += 8) { +- if (getbits(net, i + 7, 8)) +- break; +- } +- +- return (unsigned int) 32 - i; +-} +- +-static char *inet_fill_net(const char *net_num, char *net) +-{ +- char *np; +- unsigned int dots = 3; +- +- if (strlen(net_num) > INET_ADDRSTRLEN) +- return NULL; +- +- if (!isdigit(*net_num)) +- return NULL; +- +- *net = '\0'; +- strcpy(net, net_num); +- +- np = net; +- while (*np++) { +- if (*np == '.') { +- np++; +- dots--; +- if (!*np && dots) +- strcat(net, "0"); +- continue; +- } +- +- if ((*np && !isdigit(*np)) || dots < 0) { +- *net = '\0'; +- return NULL; +- } +- } +- +- while (dots--) +- strcat(net, ".0"); +- +- return net; +-} +- +-static int match_network(const char *network) +-{ +- struct netent *pnent, nent; +- const char *pcnet; +- char *net, cnet[MAX_NETWORK_LEN], mask[4], *pmask; +- unsigned int size; +- size_t l_network = strlen(network) + 1; +- int status; +- +- if (l_network > MAX_NETWORK_LEN) { +- error(LOGOPT_ANY, +- "match string \"%s\" too long", network); +- return 0; +- } +- +- net = alloca(l_network); +- if (!net) +- return 0; +- memset(net, 0, l_network); +- strcpy(net, network); +- +- if ((pmask = strchr(net, '/'))) +- *pmask++ = '\0'; +- +- status = pthread_mutex_lock(&networks_mutex); +- if (status) +- fatal(status); +- +- pnent = getnetbyname(net); +- if (pnent) +- memcpy(&nent, pnent, sizeof(struct netent)); +- +- status = pthread_mutex_unlock(&networks_mutex); +- if (status) +- fatal(status); +- +- if (pnent) { +- uint32_t n_net; +- +- switch (nent.n_addrtype) { +- case AF_INET: +- n_net = ntohl(nent.n_net); +- pcnet = inet_ntop(AF_INET, &n_net, cnet, INET_ADDRSTRLEN); +- if (!pcnet) +- return 0; +- +- if (!pmask) { +- size = inet_get_net_len(nent.n_net); +- if (!size) +- return 0; +- } +- break; +- +- case AF_INET6: +- return 0; +- +- default: +- return 0; +- } +- } else { +- int ret; +- +- if (strchr(net, ':')) { +- return 0; +- } else { +- struct in_addr addr; +- +- pcnet = inet_fill_net(net, cnet); +- if (!pcnet) +- return 0; +- +- ret = inet_pton(AF_INET, pcnet, &addr); +- if (ret <= 0) +- return 0; +- +- if (!pmask) { +- uint32_t nl_addr = htonl(addr.s_addr); +- size = inet_get_net_len(nl_addr); +- if (!size) +- return 0; +- } +- } +- } +- +- if (!pmask) { +- if (sprintf(mask, "%u", size) <= 0) +- return 0; +- pmask = mask; +- } +- +- debug(LOGOPT_ANY, "pcnet %s pmask %s", pcnet, pmask); +- +- return masked_match(pcnet, pmask); +-} +- +-/* +- * Two export formats need to be understood to cater for different +- * NFS server exports. +- * +- * (host|wildcard|network[/mask]|@netgroup) +- * +- * A host name which can be cannonical. +- * A wildcard host name containing "*" and "?" with the usual meaning. +- * A network in numbers and dots form with optional mask given as +- * either a length or as numbers and dots. +- * A netgroup identified by the prefix "@". +- * +- * [-](host|domain suffix|netgroup|@network[/mask]) +- * +- * A host name which can be cannonical. +- * A domain suffix identified by a leading "." which will match all +- * hosts in the given domain. +- * A netgroup. +- * A network identified by the prefix "@" given in numbers and dots +- * form or as a network name with optional mask given as either a +- * length or as numbers and dots. +- * A "-" prefix can be appended to indicate access is denied. +- */ +-static int host_match(char *pattern) +-{ +- unsigned int negate = (*pattern == '-'); +- const char *m_pattern = (negate ? pattern + 1 : pattern); +- char myname[MAXHOSTNAMELEN + 1] = "\0"; +- int ret = 0; +- +- if (gethostname(myname, MAXHOSTNAMELEN)) +- return 0; +- +- if (yp_get_default_domain(&domain)) +- domain = NULL; +- +- if (*m_pattern == '@') { +- /* +- * The pattern begins with an "@" so it's a network +- * spec or it's a netgroup. +- */ +- ret = match_network(m_pattern + 1); +- if (!ret) +- ret = innetgr(m_pattern + 1, myname, NULL, domain); +- } else if (*m_pattern == '.') { +- size_t m_len = strlen(m_pattern); +- char *has_dot = strchr(myname, '.'); +- /* +- * The pattern starts with a "." so it's a domain spec +- * of some sort. +- * +- * If the host name contains a dot then it must be either +- * a cannonical name or a simple NIS name.domain. So +- * perform a string match. Otherwise, append the domain +- * pattern to our simple name and try a wildcard pattern +- * match against the interfaces. +- */ +- if (has_dot) { +- if (strlen(has_dot) == m_len) +- ret = !memcmp(has_dot, m_pattern, m_len); +- } else { +- char *w_pattern = alloca(m_len + 2); +- if (w_pattern) { +- strcpy(w_pattern, "*"); +- strcat(w_pattern, m_pattern); +- ret = fqdn_match(w_pattern); +- } +- } +- } else if (!strcmp(m_pattern, "gss/krb5")) { +- /* Leave this to the GSS layer */ +- return 1; +- } else { +- /* +- * Otherwise it's a network name or host name +- */ +- ret = match_network(m_pattern); +- if (!ret) +- /* if not then try to match host name */ +- ret = string_match(myname, m_pattern); +- } +- +- if (negate && ret) +- ret = -1; +- +- return ret; +-} +- +-static int rpc_export_allowed(groups grouplist) +-{ +- groups grp = grouplist; +- +- /* NULL group list => everyone */ +- if (!grp) +- return 1; +- +- while (grp) { +- int allowed = host_match(grp->gr_name); +- /* Explicitly denied access */ +- if (allowed == -1) +- return 0; +- else if (allowed) +- return 1; +- grp = grp->gr_next; +- } +- return 0; +-} +- +-exports rpc_exports_prune(exports list) +-{ +- exports head = list; +- exports exp; +- exports last; +- int res; +- +- exp = list; +- last = NULL; +- while (exp) { +- res = rpc_export_allowed(exp->ex_groups); +- if (!res) { +- if (last == NULL) { +- head = exp->ex_next; +- rpc_export_free(exp); +- exp = head; +- } else { +- last->ex_next = exp->ex_next; +- rpc_export_free(exp); +- exp = last->ex_next; +- } +- continue; +- } +- last = exp; +- exp = exp->ex_next; +- } +- return head; +-} +- + exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option) + { + struct conn_info info; +diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c +index 1f8fa15..d711611 100644 +--- a/modules/lookup_hosts.c ++++ b/modules/lookup_hosts.c +@@ -45,7 +45,6 @@ struct lookup_context { + int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ + + exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option); +-exports rpc_exports_prune(exports list); + void rpc_exports_free(exports list); + + int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context) +@@ -207,9 +206,6 @@ done: + + exp = rpc_get_exports(name, 10, 0, RPC_CLOSE_NOLINGER); + +- /* Check exports for obvious ones we don't have access to */ +- /*exp = rpc_exports_prune(exp);*/ +- + mapent = NULL; + while (exp) { + if (mapent) { diff --git a/autofs-5.0.2-reread-config-on-hup.patch b/autofs-5.0.2-reread-config-on-hup.patch index 85afb5b..7408520 100644 --- a/autofs-5.0.2-reread-config-on-hup.patch +++ b/autofs-5.0.2-reread-config-on-hup.patch @@ -1,7 +1,36 @@ -diff -up autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup autofs-5.0.2/modules/cyrus-sasl.c ---- autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 -+++ autofs-5.0.2/modules/cyrus-sasl.c 2007-11-20 15:00:13.000000000 +0900 -@@ -528,6 +528,7 @@ sasl_do_kinit(struct lookup_context *ctx +diff --git a/daemon/automount.c b/daemon/automount.c +index e9cae4e..3d6a703 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -986,6 +986,8 @@ static void *do_read_master(void *arg) + if (status) + fatal(status); + ++ defaults_read_config(); ++ + status = master_read_master(master, age, readall); + + master->reading = 0; +diff --git a/lib/master.c b/lib/master.c +index da05bb6..637ce04 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -1169,6 +1169,10 @@ int master_mount_mounts(struct master *master, time_t age, int readall) + continue; + } + ++ master_source_writelock(this); ++ lookup_close_lookup(ap); ++ master_source_unlock(this); ++ + cache_readlock(nc); + ne = cache_lookup_distinct(nc, this->path); + if (ne && this->age > ne->age) { +diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c +index 8821f84..9aac792 100644 +--- a/modules/cyrus-sasl.c ++++ b/modules/cyrus-sasl.c +@@ -528,6 +528,7 @@ sasl_do_kinit(struct lookup_context *ctxt) return 0; out_cleanup_unparse: @@ -9,10 +38,11 @@ diff -up autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup autofs-5.0.2/mod krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name); out_cleanup_cc: status = pthread_mutex_lock(&krb5cc_mutex); -diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/modules/lookup_ldap.c ---- autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 -+++ autofs-5.0.2/modules/lookup_ldap.c 2007-11-20 15:00:13.000000000 +0900 -@@ -174,7 +174,7 @@ LDAP *init_ldap_connection(struct lookup +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 49a9a9b..2baf8b8 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -174,7 +174,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) { char buf[PARSE_MAX_BUF]; @@ -21,7 +51,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/mo LDAPMessage *result = NULL, *e; struct ldap_searchdn *sdns = NULL; char *attrs[2]; -@@ -225,15 +225,18 @@ static int get_query_dn(LDAP *ldap, stru +@@ -225,15 +225,18 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla if (!ctxt->base) { sdns = defaults_get_searchdns(); @@ -43,7 +73,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/mo debug(LOGOPT_NONE, MODPREFIX "check search base list"); -@@ -269,7 +272,6 @@ static int get_query_dn(LDAP *ldap, stru +@@ -269,7 +272,6 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla if (e) { dn = ldap_get_dn(ldap, e); debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); @@ -51,7 +81,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/mo } else { debug(LOGOPT_NONE, MODPREFIX "query succeeded, no matches for %s", -@@ -278,7 +280,16 @@ static int get_query_dn(LDAP *ldap, stru +@@ -278,7 +280,16 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla return 0; } @@ -69,7 +99,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/mo return 1; } -@@ -1018,7 +1029,7 @@ static void free_context(struct lookup_c +@@ -1018,7 +1029,7 @@ static void free_context(struct lookup_context *ctxt) if (ctxt->mapname) free(ctxt->mapname); if (ctxt->qdn) @@ -78,7 +108,7 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/mo if (ctxt->server) free(ctxt->server); if (ctxt->cur_host) -@@ -1600,14 +1611,14 @@ static int lookup_one(struct autofs_poin +@@ -1600,14 +1611,14 @@ static int lookup_one(struct autofs_point *ap, } query[ql] = '\0'; @@ -96,29 +126,3 @@ diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/mo rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result); if ((rv != LDAP_SUCCESS) || !result) { -diff -up autofs-5.0.2/daemon/automount.c.reread-config-on-hup autofs-5.0.2/daemon/automount.c ---- autofs-5.0.2/daemon/automount.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 -+++ autofs-5.0.2/daemon/automount.c 2007-11-20 15:00:13.000000000 +0900 -@@ -978,6 +978,8 @@ static void *do_read_master(void *arg) - if (status) - fatal(status); - -+ defaults_read_config(); -+ - status = master_read_master(master, age, readall); - - master->reading = 0; -diff -up autofs-5.0.2/lib/master.c.reread-config-on-hup autofs-5.0.2/lib/master.c ---- autofs-5.0.2/lib/master.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 -+++ autofs-5.0.2/lib/master.c 2007-11-20 15:00:13.000000000 +0900 -@@ -1170,6 +1170,10 @@ int master_mount_mounts(struct master *m - continue; - } - -+ master_source_writelock(this); -+ lookup_close_lookup(ap); -+ master_source_unlock(this); -+ - cache_readlock(nc); - ne = cache_lookup_distinct(nc, this->path); - if (ne && this->age > ne->age) { diff --git a/autofs-5.0.2-start-pipe-buff-size.patch b/autofs-5.0.2-start-pipe-buff-size.patch new file mode 100644 index 0000000..e9a9159 --- /dev/null +++ b/autofs-5.0.2-start-pipe-buff-size.patch @@ -0,0 +1,28 @@ +diff --git a/daemon/automount.c b/daemon/automount.c +index 7becad5..f31ec11 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -1125,7 +1125,7 @@ static void become_daemon(unsigned foreground) + if (pid > 0) { + int r; + close(start_pipefd[1]); +- r = read(start_pipefd[0], pst_stat, sizeof(pst_stat)); ++ r = read(start_pipefd[0], pst_stat, sizeof(*pst_stat)); + if (r < 0) + exit(1); + exit(*pst_stat); +@@ -2061,12 +2061,12 @@ int main(int argc, char *argv[]) + if (!master_read_master(master_list, age, 0)) { + master_kill(master_list); + *pst_stat = 3; +- res = write(start_pipefd[1], pst_stat, sizeof(pst_stat)); ++ res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + exit(3); + } + +- res = write(start_pipefd[1], pst_stat, sizeof(pst_stat)); ++ res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat)); + close(start_pipefd[1]); + + state_mach_thid = pthread_self(); diff --git a/autofs-5.0.2-submount-shutdown-race.patch b/autofs-5.0.2-submount-shutdown-race.patch new file mode 100644 index 0000000..59565a2 --- /dev/null +++ b/autofs-5.0.2-submount-shutdown-race.patch @@ -0,0 +1,172 @@ +diff --git a/daemon/automount.c b/daemon/automount.c +index f31ec11..afbcb56 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -1564,9 +1564,24 @@ void *handle_mounts(void *arg) + } + + /* OK to exit */ +- if (ap->state == ST_SHUTDOWN || result) { +- state_mutex_unlock(ap); +- break; ++ if (ap->state == ST_SHUTDOWN) { ++ if (result) { ++ state_mutex_unlock(ap); ++ break; ++ } ++#ifdef ENABLE_IGNORE_BUSY_MOUNTS ++ /* ++ * There weren't any active mounts but if the ++ * filesystem is busy there may be a mount ++ * request in progress so return to the ready ++ * state unless a shutdown has been explicitly ++ * requested. ++ */ ++ if (ap->shutdown) { ++ state_mutex_unlock(ap); ++ break; ++ } ++#endif + } + + /* Failed shutdown returns to ready */ +diff --git a/daemon/direct.c b/daemon/direct.c +index 619efce..529f143 100644 +--- a/daemon/direct.c ++++ b/daemon/direct.c +@@ -1494,7 +1494,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ + (unsigned long) pkt->wait_queue_token, me->key, pkt->pid); + + /* Ignore packet if we're trying to shut down */ +- if (ap->state == ST_SHUTDOWN_PENDING || ++ if (ap->shutdown || + ap->state == ST_SHUTDOWN_FORCE || + ap->state == ST_SHUTDOWN) { + send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token); +diff --git a/daemon/indirect.c b/daemon/indirect.c +index f6b93d0..fd94e59 100644 +--- a/daemon/indirect.c ++++ b/daemon/indirect.c +@@ -863,7 +863,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin + (unsigned long) pkt->wait_queue_token, pkt->name, pkt->pid); + + /* Ignore packet if we're trying to shut down */ +- if (ap->state == ST_SHUTDOWN_PENDING || ++ if (ap->shutdown || + ap->state == ST_SHUTDOWN_FORCE || + ap->state == ST_SHUTDOWN) { + send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token); +diff --git a/daemon/lookup.c b/daemon/lookup.c +index eb72411..eac6053 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -928,10 +928,17 @@ void lookup_close_lookup(struct autofs_point *ap) + if (!map) + return; + ++ /* ++ * Make sure we don't kill the context if a mount ++ * request has come in while were shutting down. ++ */ ++ master_source_writelock(ap->entry); + while (map) { + lookup_close_lookup_instances(map); + map = map->next; + } ++ master_source_unlock(ap->entry); ++ + return; + } + +diff --git a/daemon/state.c b/daemon/state.c +index 5bccfef..5804707 100644 +--- a/daemon/state.c ++++ b/daemon/state.c +@@ -113,6 +113,8 @@ void expire_cleanup(void *arg) + + /* Check to see if expire process finished */ + if (thid == ap->exp_thread) { ++ int rv, idle; ++ + ap->exp_thread = 0; + + switch (ap->state) { +@@ -133,8 +135,6 @@ void expire_cleanup(void *arg) + * allowing it to shutdown. + */ + if (ap->submount && !success) { +- int rv, idle; +- + rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &idle); + if (!rv && idle && ap->submount > 1) { + next = ST_SHUTDOWN_PENDING; +@@ -155,6 +155,19 @@ void expire_cleanup(void *arg) + break; + + case ST_SHUTDOWN_PENDING: ++ /* ++ * If we reveive a mount request while trying to ++ * shutdown return to ready state unless we have ++ * been signaled to shutdown. ++ */ ++ rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &idle); ++ if (!idle && !ap->shutdown) { ++ next = ST_READY; ++ if (!ap->submount) ++ alarm_add(ap, ap->exp_runfreq); ++ break; ++ } ++ + next = ST_SHUTDOWN; + #ifdef ENABLE_IGNORE_BUSY_MOUNTS + break; +@@ -200,6 +213,7 @@ static unsigned int st_ready(struct autofs_point *ap) + debug(ap->logopt, + "st_ready(): state = %d path %s", ap->state, ap->path); + ++ ap->shutdown = 0; + ap->state = ST_READY; + + if (ap->submount) +diff --git a/include/automount.h b/include/automount.h +index 133fd32..cd8ce7b 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -461,6 +461,7 @@ struct autofs_point { + unsigned int mounts_signaled; /* Submount signals task complete */ + struct list_head mounts; /* List of autofs mounts at current level */ + unsigned int submount; /* Is this a submount */ ++ unsigned int shutdown; /* Shutdown notification */ + unsigned int submnt_count; /* Number of submounts */ + struct list_head submounts; /* List of child submounts */ + }; +diff --git a/lib/master.c b/lib/master.c +index c001d20..ed82131 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -94,6 +94,7 @@ int master_add_autofs_point(struct master_mapent *entry, + ap->submount = submount; + INIT_LIST_HEAD(&ap->mounts); + INIT_LIST_HEAD(&ap->submounts); ++ ap->shutdown = 0; + + status = pthread_mutex_init(&ap->state_mutex, NULL); + if (status) { +@@ -968,6 +969,7 @@ void master_notify_state_change(struct master *master, int sig) + if (ap->state != ST_SHUTDOWN_PENDING && + ap->state != ST_SHUTDOWN_FORCE) { + next = ST_SHUTDOWN_PENDING; ++ ap->shutdown = 1; + nextstate(state_pipe, next); + } + break; +@@ -1180,9 +1182,7 @@ int master_mount_mounts(struct master *master, time_t age, int readall) + continue; + } + +- master_source_writelock(this); + lookup_close_lookup(ap); +- master_source_unlock(this); + + cache_readlock(nc); + ne = cache_lookup_distinct(nc, this->path); diff --git a/autofs-5.0.3-basedn-with-spaces-fix-3.patch b/autofs-5.0.3-basedn-with-spaces-fix-3.patch new file mode 100644 index 0000000..f4cd425 --- /dev/null +++ b/autofs-5.0.3-basedn-with-spaces-fix-3.patch @@ -0,0 +1,13 @@ +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 2a6fdf9..7f1de90 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -289,7 +289,7 @@ OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeo + return EQUAL; + } + +- {DNNAMESTR1}/"," { ++ {DNNAMESTR1}/","{DNATTRSTR}"=" { + strcpy(master_lval.strtype, master_text); + return DNNAME; + } diff --git a/autofs-5.0.3-correct-ldap-lib.patch b/autofs-5.0.3-correct-ldap-lib.patch new file mode 100644 index 0000000..7d72f26 --- /dev/null +++ b/autofs-5.0.3-correct-ldap-lib.patch @@ -0,0 +1,66 @@ +diff --git a/aclocal.m4 b/aclocal.m4 +index f24e076..a1105ae 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -232,7 +232,7 @@ AC_DEFUN([AF_CHECK_FUNC_LDAP_CREATE_PAGE_CONTROL], + + # save current ldflags + af_check_ldap_create_page_control_save_ldflags="$LDFLAGS" +-LDFLAGS="$LDFLAGS -lldap_r" ++LDFLAGS="$LDFLAGS -lldap" + + AC_TRY_LINK( + [ #include ], +@@ -265,7 +265,7 @@ AC_DEFUN([AF_CHECK_FUNC_LDAP_PARSE_PAGE_CONTROL], + + # save current ldflags + af_check_ldap_parse_page_control_save_ldflags="$LDFLAGS" +-LDFLAGS="$LDFLAGS -lldap_r" ++LDFLAGS="$LDFLAGS -lldap" + + AC_TRY_LINK( + [ #include ], +diff --git a/configure b/configure +index e872392..0d3268c 100755 +--- a/configure ++++ b/configure +@@ -4563,7 +4563,7 @@ fi + { echo "$as_me:$LINENO: result: $ac_cv_lib_ldap_ldap_initialize" >&5 + echo "${ECHO_T}$ac_cv_lib_ldap_ldap_initialize" >&6; } + if test $ac_cv_lib_ldap_ldap_initialize = yes; then +- HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap_r -llber -lresolv" ++ HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap -llber -lresolv" + fi + + if test "$HAVE_LDAP" = "1"; then +@@ -4578,7 +4578,7 @@ echo $ECHO_N "checking for ldap_create_page_control in -lldap... $ECHO_C" >&6; } + + # save current ldflags + af_check_ldap_create_page_control_save_ldflags="$LDFLAGS" +-LDFLAGS="$LDFLAGS -lldap_r" ++LDFLAGS="$LDFLAGS -lldap" + + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +@@ -4648,7 +4648,7 @@ echo $ECHO_N "checking for ldap_parse_page_control in -lldap... $ECHO_C" >&6; } + + # save current ldflags + af_check_ldap_parse_page_control_save_ldflags="$LDFLAGS" +-LDFLAGS="$LDFLAGS -lldap_r" ++LDFLAGS="$LDFLAGS -lldap" + + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +diff --git a/configure.in b/configure.in +index a9c86dd..27b9bec 100644 +--- a/configure.in ++++ b/configure.in +@@ -197,7 +197,7 @@ AC_ARG_WITH(openldap, + if test -z "$HAVE_LDAP" -o "$HAVE_LDAP" != "0"; then + HAVE_LDAP=0 + LDAP_FLAGS="$LDAP_FLAGS -DLDAP_DEPRECATED=1" +- AC_CHECK_LIB(ldap, ldap_initialize, HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap_r -llber -lresolv", , ++ AC_CHECK_LIB(ldap, ldap_initialize, HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap -llber -lresolv", , + -llber -lresolv $LIBS) + if test "$HAVE_LDAP" = "1"; then + AC_DEFINE(WITH_LDAP,1, diff --git a/autofs-5.0.3-dont-fail-on-empty-master-fix-2.patch b/autofs-5.0.3-dont-fail-on-empty-master-fix-2.patch new file mode 100644 index 0000000..c4b9ebe --- /dev/null +++ b/autofs-5.0.3-dont-fail-on-empty-master-fix-2.patch @@ -0,0 +1,40 @@ +diff --git a/lib/master.c b/lib/master.c +index ed82131..4a34dd4 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -799,21 +799,13 @@ int master_read_master(struct master *master, time_t age, int readall) + + master_init_scan(); + +- if (!lookup_nss_read_master(master, age)) { +- error(logopt, +- "can't read master map %s", master->name); +- return 0; +- } +- ++ lookup_nss_read_master(master, age); + master_mount_mounts(master, age, readall); + + master_mutex_lock(); + +- if (list_empty(&master->mounts)) { +- master_mutex_unlock(); ++ if (list_empty(&master->mounts)) + warn(logopt, "no mounts in table"); +- return 1; +- } + + master_mutex_unlock(); + +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index b01eea6..466690a 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -475,6 +475,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + "failed to read included master map %s", + master->name); + if (!master->recurse) { ++ master->name = save_name; + master->depth--; + master->recurse = 0; + fclose(f); diff --git a/autofs-5.0.3-expire-works-too-hard.patch b/autofs-5.0.3-expire-works-too-hard.patch new file mode 100644 index 0000000..44ebde0 --- /dev/null +++ b/autofs-5.0.3-expire-works-too-hard.patch @@ -0,0 +1,47 @@ +diff --git a/daemon/direct.c b/daemon/direct.c +index 529f143..760fbd4 100644 +--- a/daemon/direct.c ++++ b/daemon/direct.c +@@ -824,11 +824,16 @@ static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsig + if (errno == EBADF || errno == EINVAL) + return 1; + +- /* Other than need to wait for the kernel ? */ +- if (errno != EAGAIN) +- return 0; ++ /* ++ * Other than EAGAIN is an expire error so continue. ++ * Kernel try the same mount again, limited by ++ * retries (ie. number of mounts directly under ++ * mount point, should always be one for direct ++ * mounts). ++ */ ++ if (errno == EAGAIN) ++ break; + } +- + nanosleep(&tm, NULL); + } + +diff --git a/daemon/indirect.c b/daemon/indirect.c +index fd94e59..39b42da 100644 +--- a/daemon/indirect.c ++++ b/daemon/indirect.c +@@ -344,11 +344,13 @@ static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *pat + if (errno == EBADF || errno == EINVAL) + return 1; + +- /* Other than need to wait for the kernel ? */ +- if (errno != EAGAIN) +- return 0; ++ /* ++ * Other than EAGAIN is an expire error so continue. ++ * Kernel will try the next mount. ++ */ ++ if (errno == EAGAIN) ++ break; + } +- + nanosleep(&tm, NULL); + } + diff --git a/autofs-5.0.3-ldap-page-control-configure-fix.patch b/autofs-5.0.3-ldap-page-control-configure-fix.patch new file mode 100644 index 0000000..222eaf1 --- /dev/null +++ b/autofs-5.0.3-ldap-page-control-configure-fix.patch @@ -0,0 +1,394 @@ +diff --git a/aclocal.m4 b/aclocal.m4 +index 118ef0d..f24e076 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -222,3 +222,69 @@ AC_TRY_LINK( + LDFLAGS="$af_check_hesiod_save_ldflags" + ]) + ++dnl -------------------------------------------------------------------------- ++dnl AF_CHECK_FUNC_LDAP_CREATE_PAGE_CONTROL ++dnl ++dnl Check for function ldap_create_page_control ++dnl -------------------------------------------------------------------------- ++AC_DEFUN([AF_CHECK_FUNC_LDAP_CREATE_PAGE_CONTROL], ++[AC_MSG_CHECKING(for ldap_create_page_control in -lldap) ++ ++# save current ldflags ++af_check_ldap_create_page_control_save_ldflags="$LDFLAGS" ++LDFLAGS="$LDFLAGS -lldap_r" ++ ++AC_TRY_LINK( ++ [ #include ], ++ [ LDAP *ld; ++ ber_int_t ps; ++ struct berval *c; ++ int ic, ret; ++ LDAPControl **clp; ++ ret = ldap_create_page_control(ld,ps,c,ic,clp); ], ++ [ af_have_ldap_create_page_control=yes ++ AC_MSG_RESULT(yes) ], ++ [ AC_MSG_RESULT(no) ]) ++ ++if test "$af_have_ldap_create_page_control" = "yes"; then ++ AC_DEFINE(HAVE_LDAP_CREATE_PAGE_CONTROL, 1, ++ [Define to 1 if you have the `ldap_create_page_control' function.]) ++fi ++ ++# restore ldflags ++LDFLAGS="$af_check_ldap_create_page_control_save_ldflags" ++]) ++ ++dnl -------------------------------------------------------------------------- ++dnl AF_CHECK_FUNC_LDAP_PARSE_PAGE_CONTROL ++dnl ++dnl Check for function ldap_parse_page_control ++dnl -------------------------------------------------------------------------- ++AC_DEFUN([AF_CHECK_FUNC_LDAP_PARSE_PAGE_CONTROL], ++[AC_MSG_CHECKING(for ldap_parse_page_control in -lldap) ++ ++# save current ldflags ++af_check_ldap_parse_page_control_save_ldflags="$LDFLAGS" ++LDFLAGS="$LDFLAGS -lldap_r" ++ ++AC_TRY_LINK( ++ [ #include ], ++ [ LDAP *ld; ++ ber_int_t ct; ++ struct berval *c; ++ int ret; ++ LDAPControl **clp; ++ ret = ldap_parse_page_control(ld,clp,ct,c); ], ++ [ af_have_ldap_parse_page_control=yes ++ AC_MSG_RESULT(yes) ], ++ [ AC_MSG_RESULT(no) ]) ++ ++if test "$af_have_ldap_create_page_control" = "yes"; then ++ AC_DEFINE(HAVE_LDAP_PARSE_PAGE_CONTROL, 1, ++ [Define to 1 if you have the `ldap_parse_page_control' function.]) ++fi ++ ++# restore ldflags ++LDFLAGS="$af_check_ldap_parse_page_control_save_ldflags" ++]) ++ +diff --git a/configure b/configure +index d212b05..e872392 100755 +--- a/configure ++++ b/configure +@@ -3631,7 +3631,7 @@ if test "${with_hesiod+set}" = set; then + fi + + +-if test -z "$HAVE_HESIOD" ++if test -z "$HAVE_HESIOD" -o "$HAVE_HESIOD" != "0" + then + HAVE_HESIOD=0 + { echo "$as_me:$LINENO: checking for libhesiod" >&5 +@@ -4498,7 +4498,7 @@ if test "${with_openldap+set}" = set; then + + fi + +-if test -z "$HAVE_LDAP"; then ++if test -z "$HAVE_LDAP" -o "$HAVE_LDAP" != "0"; then + HAVE_LDAP=0 + LDAP_FLAGS="$LDAP_FLAGS -DLDAP_DEPRECATED=1" + { echo "$as_me:$LINENO: checking for ldap_initialize in -lldap" >&5 +@@ -4566,71 +4566,106 @@ if test $ac_cv_lib_ldap_ldap_initialize = yes; then + HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap_r -llber -lresolv" + fi + +- if test "$HAVE_LDAP" == "1"; then ++ if test "$HAVE_LDAP" = "1"; then + + cat >>confdefs.h <<\_ACEOF + #define WITH_LDAP 1 + _ACEOF + + fi ++ { echo "$as_me:$LINENO: checking for ldap_create_page_control in -lldap" >&5 ++echo $ECHO_N "checking for ldap_create_page_control in -lldap... $ECHO_C" >&6; } ++ ++# save current ldflags ++af_check_ldap_create_page_control_save_ldflags="$LDFLAGS" ++LDFLAGS="$LDFLAGS -lldap_r" ++ ++cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++ #include ++int ++main () ++{ ++ LDAP *ld; ++ ber_int_t ps; ++ struct berval *c; ++ int ic, ret; ++ LDAPControl **clp; ++ ret = ldap_create_page_control(ld,ps,c,ic,clp); ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext conftest$ac_exeext ++if { (ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ++ (eval "$ac_link") 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && { ++ test -z "$ac_c_werror_flag" || ++ test ! -s conftest.err ++ } && test -s conftest$ac_exeext && ++ $as_test_x conftest$ac_exeext; then ++ af_have_ldap_create_page_control=yes ++ { echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6; } ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } + fi + ++rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ ++ conftest$ac_exeext conftest.$ac_ext + ++if test "$af_have_ldap_create_page_control" = "yes"; then + ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_LDAP_CREATE_PAGE_CONTROL 1 ++_ACEOF + +-LDFLAGS="${AF_tmp_ldflags}" ++fi + ++# restore ldflags ++LDFLAGS="$af_check_ldap_create_page_control_save_ldflags" + ++ { echo "$as_me:$LINENO: checking for ldap_parse_page_control in -lldap" >&5 ++echo $ECHO_N "checking for ldap_parse_page_control in -lldap... $ECHO_C" >&6; } + +-for ac_func in ldap_create_page_control ldap_parse_page_control +-do +-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +-{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- cat >conftest.$ac_ext <<_ACEOF ++# save current ldflags ++af_check_ldap_parse_page_control_save_ldflags="$LDFLAGS" ++LDFLAGS="$LDFLAGS -lldap_r" ++ ++cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ + _ACEOF + cat confdefs.h >>conftest.$ac_ext + cat >>conftest.$ac_ext <<_ACEOF + /* end confdefs.h. */ +-/* Define $ac_func to an innocuous variant, in case declares $ac_func. +- For example, HP-UX 11i declares gettimeofday. */ +-#define $ac_func innocuous_$ac_func +- +-/* System header to define __stub macros and hopefully few prototypes, +- which can conflict with char $ac_func (); below. +- Prefer to if __STDC__ is defined, since +- exists even on freestanding compilers. */ +- +-#ifdef __STDC__ +-# include +-#else +-# include +-#endif +- +-#undef $ac_func +- +-/* Override any GCC internal prototype to avoid an error. +- Use char because int might match the return type of a GCC +- builtin and then its argument prototype would still apply. */ +-#ifdef __cplusplus +-extern "C" +-#endif +-char $ac_func (); +-/* The GNU C library defines this for functions which it implements +- to always fail with ENOSYS. Some functions are actually named +- something starting with __ and the normal name is an alias. */ +-#if defined __stub_$ac_func || defined __stub___$ac_func +-choke me +-#endif +- ++ #include + int + main () + { +-return $ac_func (); ++ LDAP *ld; ++ ber_int_t ct; ++ struct berval *c; ++ int ret; ++ LDAPControl **clp; ++ ret = ldap_parse_page_control(ld,clp,ct,c); + ; + return 0; + } +@@ -4653,28 +4688,37 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then +- eval "$as_ac_var=yes" ++ af_have_ldap_parse_page_control=yes ++ { echo "$as_me:$LINENO: result: yes" >&5 ++echo "${ECHO_T}yes" >&6; } + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + +- eval "$as_ac_var=no" ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +-fi +-ac_res=`eval echo '${'$as_ac_var'}'` +- { echo "$as_me:$LINENO: result: $ac_res" >&5 +-echo "${ECHO_T}$ac_res" >&6; } +-if test `eval echo '${'$as_ac_var'}'` = yes; then +- cat >>confdefs.h <<_ACEOF +-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 ++ ++if test "$af_have_ldap_create_page_control" = "yes"; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_LDAP_PARSE_PAGE_CONTROL 1 + _ACEOF + + fi +-done + ++# restore ldflags ++LDFLAGS="$af_check_ldap_parse_page_control_save_ldflags" ++ ++fi ++ ++ ++ ++ ++LDFLAGS="${AF_tmp_ldflags}" + + # + # SASL support +@@ -4703,7 +4747,7 @@ if test "${with_sasl+set}" = set; then + + fi + +-if test -z "$HAVE_SASL" -a "$HAVE_LIBXML" == "1" ++if test -z "$HAVE_SASL" -o "$HAVE_SASL" != "0" -a "$HAVE_LIBXML" == "1" + then + HAVE_SASL=0 + { echo "$as_me:$LINENO: checking for sasl_client_start in -lsasl2" >&5 +diff --git a/configure.in b/configure.in +index 952d040..a9c86dd 100644 +--- a/configure.in ++++ b/configure.in +@@ -155,7 +155,7 @@ AC_ARG_WITH(hesiod, + fi + ) + +-if test -z "$HAVE_HESIOD" ++if test -z "$HAVE_HESIOD" -o "$HAVE_HESIOD" != "0" + then + HAVE_HESIOD=0 + AF_CHECK_LIBHESIOD() +@@ -194,15 +194,17 @@ AC_ARG_WITH(openldap, + LDAP_FLAGS="-I${withval}/include" + fi + ) +-if test -z "$HAVE_LDAP"; then ++if test -z "$HAVE_LDAP" -o "$HAVE_LDAP" != "0"; then + HAVE_LDAP=0 + LDAP_FLAGS="$LDAP_FLAGS -DLDAP_DEPRECATED=1" + AC_CHECK_LIB(ldap, ldap_initialize, HAVE_LDAP=1 LIBLDAP="$LIBLDAP -lldap_r -llber -lresolv", , + -llber -lresolv $LIBS) +- if test "$HAVE_LDAP" == "1"; then ++ if test "$HAVE_LDAP" = "1"; then + AC_DEFINE(WITH_LDAP,1, + [Define if using LDAP as a source of automount maps]) + fi ++ AF_CHECK_FUNC_LDAP_CREATE_PAGE_CONTROL() ++ AF_CHECK_FUNC_LDAP_PARSE_PAGE_CONTROL() + fi + + AC_SUBST(LDAP_FLAGS) +@@ -210,8 +212,6 @@ AC_SUBST(HAVE_LDAP) + AC_SUBST(LIBLDAP) + LDFLAGS="${AF_tmp_ldflags}" + +-AC_CHECK_FUNCS(ldap_create_page_control ldap_parse_page_control) +- + # + # SASL support + # configure magic taken from: +@@ -236,7 +236,7 @@ AC_ARG_WITH(sasl, + SASL_FLAGS="-I${withval}/include" + fi + ) +-if test -z "$HAVE_SASL" -a "$HAVE_LIBXML" == "1" ++if test -z "$HAVE_SASL" -o "$HAVE_SASL" != "0" -a "$HAVE_LIBXML" == "1" + then + HAVE_SASL=0 + AC_CHECK_LIB(sasl2, sasl_client_start, HAVE_SASL=1 LIBSASL="$LIBSASL -lsasl2", , -lsasl2 $LIBS) +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 0723fd8..e8530f6 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -55,7 +55,7 @@ struct ldap_search_params { + char *query, **attrs; + struct berval *cookie; + int morePages; +- unsigned int totalCount; ++ ber_int_t totalCount; + LDAPMessage *result; + time_t age; + }; +@@ -63,7 +63,7 @@ struct ldap_search_params { + static LDAP *auth_init(unsigned logopt, const char *, struct lookup_context *); + + #ifndef HAVE_LDAP_CREATE_PAGE_CONTROL +-int ldap_create_page_control(LDAP *ldap, unsigned int pagesize, ++int ldap_create_page_control(LDAP *ldap, ber_int_t pagesize, + struct berval *cookie, char isCritical, + LDAPControl **output) + { +@@ -93,7 +93,7 @@ int ldap_create_page_control(LDAP *ldap, unsigned int pagesize, + + #ifndef HAVE_LDAP_PARSE_PAGE_CONTROL + int ldap_parse_page_control(LDAP *ldap, LDAPControl **controls, +- unsigned int *totalcount, struct berval **cookie) ++ ber_int_t *totalcount, struct berval **cookie) + { + int i, rc; + BerElement *theBer; +@@ -1644,7 +1644,7 @@ static int do_paged_query(struct ldap_search_params *sp, struct lookup_context * + struct autofs_point *ap = sp->ap; + LDAPControl *pageControl=NULL, *controls[2] = { NULL, NULL }; + LDAPControl **returnedControls = NULL; +- static unsigned long pageSize = 1000; ++ static ber_int_t pageSize = 1000; + static char pagingCriticality = 'T'; + int rv, scope = LDAP_SCOPE_SUBTREE; + diff --git a/autofs-5.0.3-nfs4-tcp-only.patch b/autofs-5.0.3-nfs4-tcp-only.patch new file mode 100644 index 0000000..00761cb --- /dev/null +++ b/autofs-5.0.3-nfs4-tcp-only.patch @@ -0,0 +1,13 @@ +diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c +index 0e7aebe..df01fd6 100644 +--- a/modules/mount_nfs.c ++++ b/modules/mount_nfs.c +@@ -129,7 +129,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + } + + if (strcmp(fstype, "nfs4") == 0) +- vers = NFS4_VERS_MASK | NFS_PROTO_MASK; ++ vers = NFS4_VERS_MASK | TCP_SUPPORTED; + else + vers = NFS_VERS_MASK | NFS_PROTO_MASK; + diff --git a/autofs-5.0.3-unlink-mount-return-fix.patch b/autofs-5.0.3-unlink-mount-return-fix.patch new file mode 100644 index 0000000..e38a828 --- /dev/null +++ b/autofs-5.0.3-unlink-mount-return-fix.patch @@ -0,0 +1,40 @@ +diff --git a/daemon/direct.c b/daemon/direct.c +index 760fbd4..8d1e9c6 100644 +--- a/daemon/direct.c ++++ b/daemon/direct.c +@@ -275,7 +275,6 @@ static int unlink_mount_tree(struct autofs_point *ap, struct list_head *list) + else + rv = umount2(mnt->path, MNT_DETACH); + if (rv == -1) { +- ret = 0; + debug(ap->logopt, + "can't unlink %s from mount tree", mnt->path); + +@@ -287,6 +286,7 @@ static int unlink_mount_tree(struct autofs_point *ap, struct list_head *list) + + case ENOENT: + case EFAULT: ++ ret = 0; + warn(ap->logopt, "bad path for mount"); + break; + } +diff --git a/daemon/indirect.c b/daemon/indirect.c +index 39b42da..f0409ac 100644 +--- a/daemon/indirect.c ++++ b/daemon/indirect.c +@@ -65,7 +65,6 @@ static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts) + else + rv = umount2(this->path, MNT_DETACH); + if (rv == -1) { +- ret = 0; + debug(ap->logopt, + "can't unlink %s from mount tree", this->path); + +@@ -77,6 +76,7 @@ static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts) + + case ENOENT: + case EFAULT: ++ ret = 0; + warn(ap->logopt, "bad path for mount"); + break; + } diff --git a/autofs-5.0.3-xfn-not-supported.patch b/autofs-5.0.3-xfn-not-supported.patch new file mode 100644 index 0000000..7dfbb20 --- /dev/null +++ b/autofs-5.0.3-xfn-not-supported.patch @@ -0,0 +1,63 @@ +diff --git a/lib/master_parse.y b/lib/master_parse.y +index b450122..2184b4f 100644 +--- a/lib/master_parse.y ++++ b/lib/master_parse.y +@@ -50,6 +50,7 @@ static int add_multi_mapstr(void); + + static int master_error(const char *s); + static int master_notify(const char *s); ++static int master_msg(const char *s); + + static char *path; + static char *type; +@@ -119,6 +120,7 @@ static int master_fprintf(FILE *, char *, ...); + %token DNNAME + %token MAPHOSTS + %token MAPNULL ++%token MAPXFN + %token MAPNAME + %token NUMBER + %token OPTION +@@ -283,6 +285,12 @@ map: PATH + YYABORT; + } + } ++ | MAPXFN ++ { ++ master_notify($1); ++ master_msg("X/Open Federated Naming service not supported"); ++ YYABORT; ++ } + | MAPNULL + { + type = master_strdup($1 + 1); +@@ -598,6 +606,12 @@ static int master_notify(const char *s) + return(0); + } + ++static int master_msg(const char *s) ++{ ++ logmsg("%s", s); ++ return 0; ++} ++ + static void local_init_vars(void) + { + path = NULL; +diff --git a/lib/master_tok.l b/lib/master_tok.l +index d908047..2a6fdf9 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -215,6 +215,12 @@ OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeo + return MAPNULL; + } + ++ "-xfn" { ++ BEGIN(OPTSTR); ++ strcpy(master_lval.strtype, master_text); ++ return MAPXFN; ++ } ++ + "//" { + BEGIN(DNSTR); + yyless(0); diff --git a/autofs.spec b/autofs.spec index d6b169b..587fa88 100644 --- a/autofs.spec +++ b/autofs.spec @@ -4,7 +4,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.0.2 -Release: 26 +Release: 27 Epoch: 1 License: GPL Group: System Environment/Daemons @@ -14,49 +14,72 @@ Patch0: autofs-5.0.2-add-krb5-include.patch Patch1: autofs-5.0.2-bad-proto-init.patch Patch2: autofs-5.0.2-add-missing-multi-support.patch Patch3: autofs-5.0.2-add-multi-nsswitch-lookup.patch -Patch4: autofs-5.0.2-fix-offset-dir-create.patch -Patch5: autofs-5.0.2-quote-exports.patch -Patch6: autofs-5.0.2-hi-res-time.patch -Patch7: autofs-5.0.2-quoted-slash-alone.patch -Patch8: autofs-5.0.2-fix-dnattr-parse.patch -Patch9: autofs-5.0.2-fix-nfs-version-in-get-supported-ver-and-cost.patch -Patch10: autofs-5.0.2-fix-largefile-dumbness.patch +Patch4: autofs-5.0.2-consistent-random-selection-option-name.patch +Patch5: autofs-5.0.2-fix-offset-dir-create.patch +Patch6: autofs-5.0.2-quote-exports.patch +Patch7: autofs-5.0.2-hi-res-time.patch +Patch8: autofs-5.0.2-quoted-slash-alone.patch +Patch9: autofs-5.0.2-fix-dnattr-parse.patch +Patch10: autofs-5.0.2-fix-nfs-version-in-get-supported-ver-and-cost.patch Patch11: autofs-5.0.2-instance-stale-mark.patch -Patch12: autofs-5.0.2-dont-fail-on-empty-master.patch -Patch13: autofs-5.0.2-ldap-percent-hack.patch -Patch14: autofs-5.0.2-consistent-random-selection-option-name.patch +Patch12: autofs-5.0.2-fix-largefile-dumbness.patch +Patch13: autofs-5.0.2-dont-fail-on-empty-master.patch +Patch14: autofs-5.0.2-ldap-percent-hack.patch Patch15: autofs-5.0.2-fix-mount-nfs-nosymlink.patch Patch16: autofs-5.0.2-default-nsswitch.patch Patch17: autofs-5.0.2-add-ldap-schema-discovery.patch -Patch18: autofs-5.0.2-ldap-schema-discovery-config-update.patch -Patch19: autofs-5.0.2-libxml2-workaround.patch -Patch20: autofs-5.0.2-foreground-logging.patch -Patch21: autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch -Patch22: autofs-5.0.2-ldap-check-star.patch -Patch23: autofs-5.0.2-timeout-option-parse-fix.patch -Patch24: autofs-5.0.2-ldap-search-basedn-list.patch -Patch25: autofs-5.0.2-random-selection-fix.patch -Patch26: autofs-5.0.2-reread-config-on-hup.patch -Patch27: autofs-5.0.2-add-multiple-server-selection-option.patch -Patch28: autofs-5.0.2-submount-deadlock.patch -Patch29: autofs-5.0.2-add-ferror-check.patch -Patch30: autofs-5.0.2-autofs-5-typo.patch -Patch31: autofs-5.0.2-swallow-null-macro.patch -Patch32: autofs-5.0.2-remove-unused-export-validation-code.patch -Patch33: autofs-5.0.2-dynamic-logging.patch -Patch34: autofs-5.0.2-fix-recursive-loopback-mounts.patch -Patch35: autofs-5.0.2-log-map-reload.patch +Patch18: autofs-5.0.2-random-selection-fix.patch +Patch19: autofs-5.0.2-timeout-option-parse-fix.patch +Patch20: autofs-5.0.2-ldap-check-star.patch +Patch21: autofs-5.0.2-ldap-schema-discovery-config-update.patch +Patch22: autofs-5.0.2-ldap-search-basedn-list.patch +Patch23: autofs-5.0.2-libxml2-workaround.patch +Patch24: autofs-5.0.2-reread-config-on-hup.patch +Patch25: autofs-5.0.2-add-multiple-server-selection-option.patch +Patch26: autofs-5.0.2-foreground-logging.patch +Patch27: autofs-5.0.2-submount-deadlock.patch +Patch28: autofs-5.0.2-add-ferror-check.patch +Patch29: autofs-5.0.2-autofs-5-typo.patch +Patch30: autofs-5.0.2-swallow-null-macro.patch +Patch31: autofs-5.0.2-remove-unused-export-validation-code.patch +Patch32: autofs-5.0.2-dynamic-logging.patch +Patch33: autofs-5.0.2-fix-recursive-loopback-mounts.patch +Patch34: autofs-5.0.2-log-map-reload.patch +Patch35: autofs-5.0.2-basedn-with-spaces.patch Patch36: autofs-5.0.2-dynamic-logging-fixes.patch -Patch37: autofs-5.0.2-basedn-with-spaces.patch +Patch37: autofs-5.0.2-basedn-with-spaces-fix.patch Patch38: autofs-5.0.2-check-mtab-updated.patch -Patch39: autofs-5.0.2-check-auto_master.patch -Patch40: autofs-5.0.2-negative-timeout-update.patch -Patch41: autofs-5.0.2-large-groups.patch -Patch42: autofs-5.0.2-report-failed-lookups.patch -Patch43: autofs-5.0.2-dynamic-logging-non-sasl.patch -Patch44: autofs-5.0.2-singleton-host-list.patch -Patch45: autofs-5.0.2-hosts-nosuid-default.patch -Patch46: autofs-5.0.2-hosts-nodev-default.patch +Patch39: autofs-5.0.2-basedn-with-spaces-fix-2.patch +Patch40: autofs-5.0.2-check-auto_master.patch +Patch41: autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch +Patch42: autofs-5.0.2-negative-timeout-update.patch +Patch43: autofs-5.0.2-large-groups.patch +Patch44: autofs-5.0.2-report-failed-lookups.patch +Patch45: autofs-5.0.2-dynamic-logging-non-sasl.patch +Patch46: autofs-5.0.2-singleton-host-list.patch +Patch47: autofs-5.0.2-hosts-nosuid-default.patch +Patch48: autofs-5.0.2-hosts-nodev-default.patch +Patch49: autofs-5.0.2-start-pipe-buff-size.patch +Patch50: autofs-5.0.2-fix-off-by-one-lookup.patch +Patch51: autofs-5.0.2-improve-server-unavail.patch +Patch52: autofs-5.0.2-add-multiple-server-selection-option-fix.patch +Patch53: autofs-5.0.2-external-cred-cache.patch +Patch54: autofs-5.0.2-percent-hack-fix.patch +Patch55: autofs-5.0.2-quote-exports-fix.patch +Patch56: autofs-5.0.2-quell-mount-module-message.patch +Patch57: autofs-5.0.2-improve-server-unavail-fix.patch +Patch58: autofs-5.0.2-ldap-page-control.patch +Patch59: autofs-5.0.2-instance-stale-mark-update.patch +Patch60: autofs-5.0.2-submount-shutdown-race.patch +Patch61: autofs-5.0.2-ldap-search-basedn-list-fix.patch +Patch62: autofs-5.0.3-ldap-page-control-configure-fix.patch +Patch63: autofs-5.0.3-xfn-not-supported.patch +Patch64: autofs-5.0.3-basedn-with-spaces-fix-3.patch +Patch65: autofs-5.0.3-nfs4-tcp-only.patch +Patch66: autofs-5.0.3-correct-ldap-lib.patch +Patch67: autofs-5.0.3-dont-fail-on-empty-master-fix-2.patch +Patch68: autofs-5.0.3-expire-works-too-hard.patch +Patch69: autofs-5.0.3-unlink-mount-return-fix.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs Conflicts: kernel < 2.6.17 @@ -145,6 +168,29 @@ echo %{version}-%{release} > .version %patch44 -p1 %patch45 -p1 %patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 +%patch51 -p1 +%patch52 -p1 +%patch53 -p1 +%patch54 -p1 +%patch55 -p1 +%patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 %build #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir} @@ -197,6 +243,37 @@ fi %{_libdir}/autofs/ %changelog +* Thu Feb 14 2008 Ian Kent - 5.0.2-26 +- re-order and update patches to sync with upstream. + - located missing patch. + - replaced couple of patches previously altered due to incorrect ordering. +- add patches for upstream issues - synced with 5.0.3. + - fix incorrect read/write size of startup status token (Matthias Koenig). + - fix off-by-one error for lookup of map keys exactly 255 characters long. + - improve handling of server not available. + - fix LDAP_URI server selection. + - add authentication option for using an external credential cache. + - expand support for the "%" hack. + - fix to quoting for exports gathered by hosts map. + - use mount option "nosuid" for "-hosts" map unless "suid" is explicily specified. + - second attempt fixing quoting for exports gathered by hosts map. + - quell annoying "cannot open mount module" message. + - fix for improve handling of server not available. + - use mount option "nodev" for "-hosts" map unless "dev" is explicily specified. + - add LDAP paged query handling to deal with query size restrictions (Edward Newman). + - add additional case for "mark map instances stale so they aren't "cleaned" during updates". + - fix race during sub-mount shutdown. + - fix add SEARCH_BASE configuration option. +- add patches for upstream issues - post 5.0.3. + - correct configure test for ldapr page control functions. + - catch "-xfn" map type and issue "no supported" message. + - correction for handling of LDAP base dns with spaces. + - avoid using UDP for probing NFSv4 mount requests. + - use libldap instead of libldap_r (Guillaume Rousse). + - another fix for don't fail on empty master map. + - fix expire working harder than needed. + - fix unlink of mount tree incorrectly causing autofs mount fail. + * Sun Feb 3 2008 Ian Kent - 5.0.2-25 - Bug 397591 SELinux is preventing /sbin/rpc.statd (rpcd_t) "search" to (sysctl_fs_t). - remove this patch.