mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2026-01-19 07:31:35 +01:00
208 lines
6.3 KiB
Diff
208 lines
6.3 KiB
Diff
--- a/apps/openssl/s_client.c
|
|
+++ b/apps/openssl/s_client.c
|
|
@@ -56,7 +56,7 @@
|
|
* [including the GNU Public Licence.]
|
|
*/
|
|
/* ====================================================================
|
|
- * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
|
+ * Copyright (c) 1998-2017 The OpenSSL Project. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
@@ -184,6 +184,7 @@
|
|
static void sc_usage(void);
|
|
static void print_stuff(BIO * berr, SSL * con, int full);
|
|
static int ocsp_resp_cb(SSL * s, void *arg);
|
|
+static int ldap_ExtendedResponse_parse(const char *buf, long rem);
|
|
static BIO *bio_c_out = NULL;
|
|
static int c_quiet = 0;
|
|
static int c_ign_eof = 0;
|
|
@@ -234,7 +235,7 @@
|
|
BIO_printf(bio_err, " -starttls prot - use the STARTTLS command before starting TLS\n");
|
|
BIO_printf(bio_err, " for those protocols that support it, where\n");
|
|
BIO_printf(bio_err, " 'prot' defines which one to assume. Currently,\n");
|
|
- BIO_printf(bio_err, " only \"smtp\", \"lmtp\", \"pop3\", \"imap\", \"ftp\" and \"xmpp\"\n");
|
|
+ BIO_printf(bio_err, " only \"smtp\", \"lmtp\", \"pop3\", \"imap\", \"ftp\", \"xmpp\" and \"ldap\"\n");
|
|
BIO_printf(bio_err, " are supported.\n");
|
|
BIO_printf(bio_err, " -xmpphost host - connect to this virtual host on the xmpp server\n");
|
|
BIO_printf(bio_err, " -sess_out arg - file to write SSL session to\n");
|
|
@@ -284,7 +285,8 @@
|
|
PROTO_POP3,
|
|
PROTO_IMAP,
|
|
PROTO_FTP,
|
|
- PROTO_XMPP
|
|
+ PROTO_XMPP,
|
|
+ PROTO_LDAP
|
|
};
|
|
|
|
int
|
|
@@ -543,6 +545,8 @@
|
|
starttls_proto = PROTO_FTP;
|
|
else if (strcmp(*argv, "xmpp") == 0)
|
|
starttls_proto = PROTO_XMPP;
|
|
+ else if (strcmp(*argv, "ldap") == 0)
|
|
+ starttls_proto = PROTO_LDAP;
|
|
else
|
|
goto bad;
|
|
}
|
|
@@ -934,6 +938,72 @@
|
|
if (!strstr(sbuf, "<proceed"))
|
|
goto shut;
|
|
mbuf[0] = 0;
|
|
+ } else if (starttls_proto == PROTO_LDAP) {
|
|
+ /* StartTLS Operation according to RFC 4511 */
|
|
+ static char ldap_tls_genconf[] = "asn1=SEQUENCE:LDAPMessage\n"
|
|
+ "[LDAPMessage]\n"
|
|
+ "messageID=INTEGER:1\n"
|
|
+ "extendedReq=EXPLICIT:23A,IMPLICIT:0C,"
|
|
+ "FORMAT:ASCII,OCT:1.3.6.1.4.1.1466.20037\n";
|
|
+ long errline = -1;
|
|
+ char *genstr = NULL;
|
|
+ int result = -1;
|
|
+ ASN1_TYPE *atyp = NULL;
|
|
+ BIO *ldapbio = BIO_new(BIO_s_mem());
|
|
+ CONF *cnf = NCONF_new(NULL);
|
|
+
|
|
+ if (cnf == NULL) {
|
|
+ BIO_free(ldapbio);
|
|
+ goto end;
|
|
+ }
|
|
+ BIO_puts(ldapbio, ldap_tls_genconf);
|
|
+ if (NCONF_load_bio(cnf, ldapbio, &errline) <= 0) {
|
|
+ BIO_free(ldapbio);
|
|
+ NCONF_free(cnf);
|
|
+ if (errline <= 0) {
|
|
+ BIO_printf(bio_err, "NCONF_load_bio failed\n");
|
|
+ goto end;
|
|
+ } else {
|
|
+ BIO_printf(bio_err, "Error on line %ld\n", errline);
|
|
+ goto end;
|
|
+ }
|
|
+ }
|
|
+ BIO_free(ldapbio);
|
|
+ genstr = NCONF_get_string(cnf, "default", "asn1");
|
|
+ if (genstr == NULL) {
|
|
+ NCONF_free(cnf);
|
|
+ BIO_printf(bio_err, "NCONF_get_string failed\n");
|
|
+ goto end;
|
|
+ }
|
|
+ atyp = ASN1_generate_nconf(genstr, cnf);
|
|
+ if (atyp == NULL) {
|
|
+ NCONF_free(cnf);
|
|
+ BIO_printf(bio_err, "ASN1_generate_nconf failed\n");
|
|
+ goto end;
|
|
+ }
|
|
+ NCONF_free(cnf);
|
|
+
|
|
+ /* Send SSLRequest packet */
|
|
+ BIO_write(sbio, atyp->value.sequence->data,
|
|
+ atyp->value.sequence->length);
|
|
+ (void)BIO_flush(sbio);
|
|
+ ASN1_TYPE_free(atyp);
|
|
+
|
|
+ mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
|
|
+ if (mbuf_len < 0) {
|
|
+ BIO_printf(bio_err, "BIO_read failed\n");
|
|
+ goto end;
|
|
+ }
|
|
+ result = ldap_ExtendedResponse_parse(mbuf, mbuf_len);
|
|
+ if (result < 0) {
|
|
+ BIO_printf(bio_err, "ldap_ExtendedResponse_parse failed\n");
|
|
+ goto shut;
|
|
+ } else if (result > 0) {
|
|
+ BIO_printf(bio_err, "STARTTLS failed, LDAP Result Code: %i\n",
|
|
+ result);
|
|
+ goto shut;
|
|
+ }
|
|
+ mbuf_len = 0;
|
|
} else if (proxy != NULL) {
|
|
BIO_printf(sbio, "CONNECT %s HTTP/1.0\r\n\r\n", connect);
|
|
mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
|
|
@@ -1437,3 +1507,86 @@
|
|
return 1;
|
|
}
|
|
|
|
+static int ldap_ExtendedResponse_parse(const char *buf, long rem)
|
|
+{
|
|
+ const unsigned char *cur, *end;
|
|
+ long len;
|
|
+ int tag, xclass, inf, ret = -1;
|
|
+
|
|
+ cur = (const unsigned char *)buf;
|
|
+ end = cur + rem;
|
|
+
|
|
+ /*
|
|
+ * From RFC 4511:
|
|
+ *
|
|
+ * LDAPMessage ::= SEQUENCE {
|
|
+ * messageID MessageID,
|
|
+ * protocolOp CHOICE {
|
|
+ * ...
|
|
+ * extendedResp ExtendedResponse,
|
|
+ * ... },
|
|
+ * controls [0] Controls OPTIONAL }
|
|
+ *
|
|
+ * ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
|
|
+ * COMPONENTS OF LDAPResult,
|
|
+ * responseName [10] LDAPOID OPTIONAL,
|
|
+ * responseValue [11] OCTET STRING OPTIONAL }
|
|
+ *
|
|
+ * LDAPResult ::= SEQUENCE {
|
|
+ * resultCode ENUMERATED {
|
|
+ * success (0),
|
|
+ * ...
|
|
+ * other (80),
|
|
+ * ... },
|
|
+ * matchedDN LDAPDN,
|
|
+ * diagnosticMessage LDAPString,
|
|
+ * referral [3] Referral OPTIONAL }
|
|
+ */
|
|
+
|
|
+ /* pull SEQUENCE */
|
|
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
|
|
+ if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE ||
|
|
+ (rem = end - cur, len > rem)) {
|
|
+ BIO_printf(bio_err, "Unexpected LDAP response\n");
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ rem = len; /* ensure that we don't overstep the SEQUENCE */
|
|
+
|
|
+ /* pull MessageID */
|
|
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
|
|
+ if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_INTEGER ||
|
|
+ (rem = end - cur, len > rem)) {
|
|
+ BIO_printf(bio_err, "No MessageID\n");
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ cur += len; /* shall we check for MessageId match or just skip? */
|
|
+
|
|
+ /* pull [APPLICATION 24] */
|
|
+ rem = end - cur;
|
|
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
|
|
+ if (inf != V_ASN1_CONSTRUCTED || xclass != V_ASN1_APPLICATION ||
|
|
+ tag != 24) {
|
|
+ BIO_printf(bio_err, "Not ExtendedResponse\n");
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ /* pull resultCode */
|
|
+ rem = end - cur;
|
|
+ inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
|
|
+ if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_ENUMERATED || len == 0 ||
|
|
+ (rem = end - cur, len > rem)) {
|
|
+ BIO_printf(bio_err, "Not LDAPResult\n");
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ /* len should always be one, but just in case... */
|
|
+ for (ret = 0, inf = 0; inf < len; inf++) {
|
|
+ ret <<= 8;
|
|
+ ret |= cur[inf];
|
|
+ }
|
|
+ /* There is more data, but we don't care... */
|
|
+ end:
|
|
+ return ret;
|
|
+}
|