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