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