From: Todd C. Miller Date: Thu, 10 Jul 2014 21:31:11 +0000 (-0600) Subject: Add support for base64 secrets in ldap.conf and ldap.secret. X-Git-Tag: SUDO_1_8_11^2~139 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c35d7f2b046d4755e166ade10ebc346b0f2e2096;p=sudo Add support for base64 secrets in ldap.conf and ldap.secret. Based on an idea from anthony AT rlost DOT com --- diff --git a/doc/sudoers.ldap.cat b/doc/sudoers.ldap.cat index eb67c83ab..d932c7f6b 100644 --- a/doc/sudoers.ldap.cat +++ b/doc/sudoers.ldap.cat @@ -378,7 +378,15 @@ DDEESSCCRRIIPPTTIIOONN BBIINNDDPPWW _s_e_c_r_e_t The BBIINNDDPPWW parameter specifies the password to use when performing LDAP operations. This is typically used in conjunction with the - BBIINNDDDDNN parameter. + BBIINNDDDDNN parameter. The _s_e_c_r_e_t may be a plain text password or a + base64-encoded string with a ``base64:'' prefix. For example: + + BINDPW base64:dGVzdA== + + If a plain text password is used, it should be a simple string + without quotes. Plain text passwords may not include the comment + character (`#') and the escaping of special characters with a + backslash (`\') is not supported. RROOOOTTBBIINNDDDDNN _D_N The RROOOOTTBBIINNDDDDNN parameter specifies the identity, in the form of a @@ -476,12 +484,18 @@ DDEESSCCRRIIPPTTIIOONN TTLLSS__KKEEYYPPWW _s_e_c_r_e_t The TTLLSS__KKEEYYPPWW contains the password used to decrypt the key database on clients using the Tivoli Directory Server LDAP library. - This should be a simple string without quotes. The password may - not include the comment character (`#') and escaping of special - characters with a backslash (`\') is not supported. If this option - is used, _/_e_t_c_/_l_d_a_p_._c_o_n_f must not be world-readable to avoid - exposing the password. Alternately, a _s_t_a_s_h _f_i_l_e can be used to - store the password in encrypted form (see below). + The _s_e_c_r_e_t may be a plain text password or a base64-encoded string + with a ``base64:'' prefix. For example: + + TLS_KEYPW base64:dGVzdA== + + If a plain text password is used, it should be a simple string + without quotes. Plain text passwords may not include the comment + character (`#') and the escaping of special characters with a + backslash (`\') is not supported. If this option is used, + _/_e_t_c_/_l_d_a_p_._c_o_n_f must not be world-readable to avoid exposing the + password. Alternately, a _s_t_a_s_h _f_i_l_e can be used to store the + password in encrypted form (see below). If no TTLLSS__KKEEYYPPWW is specified, a _s_t_a_s_h _f_i_l_e will be used if it exists. The _s_t_a_s_h _f_i_l_e must have the same path as the file @@ -812,4 +826,4 @@ DDIISSCCLLAAIIMMEERR file distributed with ssuuddoo or http://www.sudo.ws/sudo/license.html for complete details. -Sudo 1.8.10 February 7, 2014 Sudo 1.8.10 +Sudo 1.8.11 July 10, 2014 Sudo 1.8.11 diff --git a/doc/sudoers.ldap.man.in b/doc/sudoers.ldap.man.in index 6cbd5939e..c28ff5730 100644 --- a/doc/sudoers.ldap.man.in +++ b/doc/sudoers.ldap.man.in @@ -16,7 +16,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.TH "SUDOERS.LDAP" "8" "February 7, 2014" "Sudo @PACKAGE_VERSION@" "OpenBSD System Manager's Manual" +.TH "SUDOERS.LDAP" "8" "July 10, 2014" "Sudo @PACKAGE_VERSION@" "OpenBSD System Manager's Manual" .nh .if n .ad l .SH "NAME" @@ -698,6 +698,27 @@ parameter specifies the password to use when performing LDAP operations. This is typically used in conjunction with the \fBBINDDN\fR parameter. +The +\fIsecret\fR +may be a plain text password or a base64-encoded string with a +\(lqbase64:\(rq +prefix. +For example: +.nf +.sp +.RS 10n +BINDPW base64:dGVzdA== +.RE +.fi +.RS 6n +.sp +If a plain text password is used, it should be a simple string without quotes. +Plain text passwords may not include the comment character +(\(oq#\(cq) +and the escaping of special characters with a backslash +(\(oq\e\(cq) +is not supported. +.RE .TP 6n \fBROOTBINDDN\fR \fIDN\fR The @@ -848,10 +869,24 @@ The \fBTLS_KEYPW\fR contains the password used to decrypt the key database on clients using the Tivoli Directory Server LDAP library. -This should be a simple string without quotes. -The password may not include the comment character +The +\fIsecret\fR +may be a plain text password or a base64-encoded string with a +\(lqbase64:\(rq +prefix. +For example: +.nf +.sp +.RS 10n +TLS_KEYPW base64:dGVzdA== +.RE +.fi +.RS 6n +.sp +If a plain text password is used, it should be a simple string without quotes. +Plain text passwords may not include the comment character (\(oq#\(cq) -and escaping of special characters with a backslash +and the escaping of special characters with a backslash (\(oq\e\(cq) is not supported. If this option is used, @@ -885,6 +920,7 @@ The utility can be used to manage the key database and create a \fIstash file\fR. This option is only supported by the Tivoli LDAP libraries. +.RE .TP 6n \fBTLS_RANDFILE\fR \fIfile name\fR The diff --git a/doc/sudoers.ldap.mdoc.in b/doc/sudoers.ldap.mdoc.in index 891e3e1f9..1cdc965fe 100644 --- a/doc/sudoers.ldap.mdoc.in +++ b/doc/sudoers.ldap.mdoc.in @@ -14,7 +14,7 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 7, 2014 +.Dd July 10, 2014 .Dt SUDOERS.LDAP @mansectsu@ .Os Sudo @PACKAGE_VERSION@ .Sh NAME @@ -658,6 +658,22 @@ parameter specifies the password to use when performing LDAP operations. This is typically used in conjunction with the .Sy BINDDN parameter. +The +.Ar secret +may be a plain text password or a base64-encoded string with a +.Dq base64: +prefix. +For example: +.Bd -literal -offset 4n +BINDPW base64:dGVzdA== +.Ed +.Pp +If a plain text password is used, it should be a simple string without quotes. +Plain text passwords may not include the comment character +.Pq Ql # +and the escaping of special characters with a backslash +.Pq Ql \e +is not supported. .It Sy ROOTBINDDN Ar DN The .Sy ROOTBINDDN @@ -779,10 +795,20 @@ The .Sy TLS_KEYPW contains the password used to decrypt the key database on clients using the Tivoli Directory Server LDAP library. -This should be a simple string without quotes. -The password may not include the comment character +The +.Ar secret +may be a plain text password or a base64-encoded string with a +.Dq base64: +prefix. +For example: +.Bd -literal -offset 4n +TLS_KEYPW base64:dGVzdA== +.Ed +.Pp +If a plain text password is used, it should be a simple string without quotes. +Plain text passwords may not include the comment character .Pq Ql # -and escaping of special characters with a backslash +and the escaping of special characters with a backslash .Pq Ql \e is not supported. If this option is used, diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index 8c636af0a..59d9f1d9e 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -1381,20 +1381,48 @@ sudo_ldap_build_pass2(void) debug_return_str(filt); } +/* + * Decode a secret if it is base64 encoded, else return NULL. + */ +static char * +sudo_ldap_decode_secret(const char *secret) +{ + char *result = NULL; + size_t len, reslen; + debug_decl(sudo_ldap_decode_secret, SUDO_DEBUG_LDAP) + + if (strncasecmp(secret, "base64:", sizeof("base64:") - 1) == 0) { + /* + * Decode a base64 secret. The decoded length is 3/4 the encoded + * length but padding may be missing so round up to a multiple of 4. + */ + secret += sizeof("base64:") - 1; + reslen = ((strlen(secret) + 3) / 4 * 3) + 1; + result = sudo_emalloc(reslen); + len = base64_decode(secret, result, reslen); + if (len == (size_t)-1) { + free(result); + result = NULL; + } + } + debug_return_str(result); +} + static void sudo_ldap_read_secret(const char *path) { FILE *fp; - char buf[LINE_MAX], *cp; + char buf[LINE_MAX]; debug_decl(sudo_ldap_read_secret, SUDO_DEBUG_LDAP) if ((fp = fopen(path_ldap_secret, "r")) != NULL) { if (fgets(buf, sizeof(buf), fp) != NULL) { - if ((cp = strchr(buf, '\n')) != NULL) - *cp = '\0'; + buf[strcspn(buf, "\n")] = '\0'; /* copy to bindpw and binddn */ efree(ldap_conf.bindpw); - ldap_conf.bindpw = sudo_estrdup(buf); + ldap_conf.bindpw = sudo_ldap_decode_secret(buf); + if (ldap_conf.bindpw == NULL) + ldap_conf.bindpw = sudo_estrdup(buf); efree(ldap_conf.binddn); ldap_conf.binddn = ldap_conf.rootbinddn; ldap_conf.rootbinddn = NULL; @@ -1718,9 +1746,25 @@ sudo_ldap_read_config(void) efree(cp); } + /* If rootbinddn set, read in /etc/ldap.secret if it exists. */ - if (ldap_conf.rootbinddn) + if (ldap_conf.rootbinddn) { sudo_ldap_read_secret(path_ldap_secret); + } else if (ldap_conf.bindpw) { + cp = sudo_ldap_decode_secret(ldap_conf.bindpw); + if (cp != NULL) { + efree(ldap_conf.bindpw); + ldap_conf.bindpw = cp; + } + } + + if (ldap_conf.tls_keypw) { + cp = sudo_ldap_decode_secret(ldap_conf.tls_keypw); + if (cp != NULL) { + efree(ldap_conf.tls_keypw); + ldap_conf.tls_keypw = cp; + } + } #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S /*