1 /* $NetBSD: starttls.c,v 1.1.1.4 2014/05/28 09:58:48 tron Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2014 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 18 #include "portable.h" 19 20 #include <stdio.h> 21 #include <ac/socket.h> 22 #include <ac/string.h> 23 24 #include "slap.h" 25 #include "lber_pvt.h" 26 27 const struct berval slap_EXOP_START_TLS = BER_BVC(LDAP_EXOP_START_TLS); 28 29 #ifdef HAVE_TLS 30 int 31 starttls_extop ( Operation *op, SlapReply *rs ) 32 { 33 int rc; 34 35 Statslog( LDAP_DEBUG_STATS, "%s STARTTLS\n", 36 op->o_log_prefix, 0, 0, 0, 0 ); 37 38 if ( op->ore_reqdata != NULL ) { 39 /* no request data should be provided */ 40 rs->sr_text = "no request data expected"; 41 return LDAP_PROTOCOL_ERROR; 42 } 43 44 /* acquire connection lock */ 45 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 46 47 /* can't start TLS if it is already started */ 48 if (op->o_conn->c_is_tls != 0) { 49 rs->sr_text = "TLS already started"; 50 rc = LDAP_OPERATIONS_ERROR; 51 goto done; 52 } 53 54 /* can't start TLS if there are other op's around */ 55 if (( !LDAP_STAILQ_EMPTY(&op->o_conn->c_ops) && 56 (LDAP_STAILQ_FIRST(&op->o_conn->c_ops) != op || 57 LDAP_STAILQ_NEXT(op, o_next) != NULL)) || 58 ( !LDAP_STAILQ_EMPTY(&op->o_conn->c_pending_ops) )) 59 { 60 rs->sr_text = "cannot start TLS when operations are outstanding"; 61 rc = LDAP_OPERATIONS_ERROR; 62 goto done; 63 } 64 65 if ( !( global_disallows & SLAP_DISALLOW_TLS_2_ANON ) && 66 ( op->o_conn->c_dn.bv_len != 0 ) ) 67 { 68 Statslog( LDAP_DEBUG_STATS, 69 "%s AUTHZ anonymous mech=starttls ssf=0\n", 70 op->o_log_prefix, 0, 0, 0, 0 ); 71 72 /* force to anonymous */ 73 connection2anonymous( op->o_conn ); 74 } 75 76 if ( ( global_disallows & SLAP_DISALLOW_TLS_AUTHC ) && 77 ( op->o_conn->c_dn.bv_len != 0 ) ) 78 { 79 rs->sr_text = "cannot start TLS after authentication"; 80 rc = LDAP_OPERATIONS_ERROR; 81 goto done; 82 } 83 84 /* fail if TLS could not be initialized */ 85 if ( slap_tls_ctx == NULL ) { 86 if (default_referral != NULL) { 87 /* caller will put the referral in the result */ 88 rc = LDAP_REFERRAL; 89 goto done; 90 } 91 92 rs->sr_text = "Could not initialize TLS"; 93 rc = LDAP_UNAVAILABLE; 94 goto done; 95 } 96 97 op->o_conn->c_is_tls = 1; 98 op->o_conn->c_needs_tls_accept = 1; 99 100 rc = LDAP_SUCCESS; 101 102 done: 103 /* give up connection lock */ 104 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 105 106 /* FIXME: RACE CONDITION! we give up lock before sending result 107 * Should be resolved by reworking connection state, not 108 * by moving send here (so as to ensure proper TLS sequencing) 109 */ 110 111 return rc; 112 } 113 114 #endif /* HAVE_TLS */ 115