]> git.sur5r.net Git - openldap/blob - contrib/ldapc++/src/TlsOptions.cpp
44a2b607b26349edca201e13c1c527d031a562d4
[openldap] / contrib / ldapc++ / src / TlsOptions.cpp
1 // $OpenLDAP$
2 /*
3  * Copyright 2010-2013 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include <fstream>
8 #include <sstream>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <errno.h>
12 #include <unistd.h>
13 #include <cstring>
14 #include "TlsOptions.h"
15 #include "LDAPException.h"
16
17 enum opttype {
18     INT=0,
19     STRING,
20     OTHER
21 };
22
23 typedef struct tls_optmap {
24     int optval;
25     opttype type;
26 } tls_optmap_t;
27
28 static tls_optmap_t optmap[] = {
29     { LDAP_OPT_X_TLS_CACERTFILE, STRING },
30     { LDAP_OPT_X_TLS_CACERTDIR, STRING },
31     { LDAP_OPT_X_TLS_CERTFILE, STRING },
32     { LDAP_OPT_X_TLS_KEYFILE, STRING },
33     { LDAP_OPT_X_TLS_REQUIRE_CERT, INT },
34     { LDAP_OPT_X_TLS_PROTOCOL_MIN, INT },
35     { LDAP_OPT_X_TLS_CIPHER_SUITE, STRING },
36     { LDAP_OPT_X_TLS_RANDOM_FILE, STRING },
37     { LDAP_OPT_X_TLS_CRLCHECK, INT },
38     { LDAP_OPT_X_TLS_DHFILE, STRING },
39     { LDAP_OPT_X_TLS_NEWCTX, INT }
40 };
41 #if 0 /* not implemented currently */
42         static const int TLS_CRLFILE /* GNUtls only */
43         static const int TLS_SSL_CTX  /* OpenSSL SSL* */
44         static const int TLS_CONNECT_CB
45         static const int TLS_CONNECT_ARG
46 #endif 
47
48 static void checkOpt( TlsOptions::tls_option opt, opttype type ) {
49     if ( opt < TlsOptions::CACERTFILE || opt >= TlsOptions::LASTOPT ){
50         throw( LDAPException( LDAP_PARAM_ERROR, "unknown Option" ) );
51     }
52
53     if ( optmap[opt].type != type ){
54         throw( LDAPException( LDAP_PARAM_ERROR, "not a string option" ) );
55     }
56 }
57
58 TlsOptions::TlsOptions() : m_ld(NULL) {}
59
60 TlsOptions::TlsOptions( LDAP* ld ): m_ld(ld) { }
61
62 void TlsOptions::setOption( tls_option opt, const std::string& value ) const {
63     checkOpt(opt, STRING);
64     switch(opt) {
65         case TlsOptions::CACERTFILE :
66         case TlsOptions::CERTFILE :
67         case TlsOptions::KEYFILE :
68         {
69             // check if the supplied file is actually readable
70             std::ifstream ifile(value.c_str());
71             if ( !ifile ) {
72                 throw( LDAPException( LDAP_LOCAL_ERROR, "Unable to open the supplied file for reading" ) );
73             }
74         }
75         break;
76         case TlsOptions::CACERTDIR :
77         {
78             struct stat st;
79             std::ostringstream msg;
80             bool fail=false;
81             int err = stat(value.c_str(),&st);
82             if ( err ) {
83                 msg << strerror(errno);
84                 fail = true;
85             } else {
86                 if ( !S_ISDIR(st.st_mode) ){
87                     msg << "The supplied path is not a directory.";
88                     fail = true;
89                 }
90             }
91             if ( fail ) {
92                 std::ostringstream errstr;
93                 errstr << "Error while setting Certificate Directory (" << value << "): " << msg.str();
94                 throw( LDAPException( LDAP_LOCAL_ERROR, errstr.str() ) );
95             }
96         }
97         break;
98     }
99     this->setOption( opt, value.empty() ? NULL : (void*) value.c_str() );
100 }
101
102 void TlsOptions::setOption( tls_option opt, int value ) const {
103     checkOpt(opt, INT);
104     this->setOption( opt, (void*) &value);
105 }
106
107 void TlsOptions::setOption( tls_option opt, void *value ) const {
108     int ret = ldap_set_option( m_ld, optmap[opt].optval, value);
109     if ( ret != LDAP_OPT_SUCCESS )
110     {
111         if ( ret != LDAP_OPT_ERROR ){
112             throw( LDAPException( ret ));
113         } else {
114             throw( LDAPException( LDAP_PARAM_ERROR, "error while setting TLS option" ) );
115         }
116     }
117     this->newCtx();
118 }
119
120 void TlsOptions::getOption( tls_option opt, void* value ) const {
121     int ret = ldap_get_option( m_ld, optmap[opt].optval, value);
122     if ( ret != LDAP_OPT_SUCCESS )
123     {
124         if ( ret != LDAP_OPT_ERROR ){
125             throw( LDAPException( ret ));
126         } else {
127             throw( LDAPException( LDAP_PARAM_ERROR, "error while reading TLS option" ) );
128         }
129     }
130 }
131
132 int TlsOptions::getIntOption( tls_option opt ) const {
133     int value;
134     checkOpt(opt, INT);
135     ldap_get_option( m_ld, optmap[opt].optval, (void*) &value);
136     return value;
137 }
138
139 std::string TlsOptions::getStringOption( tls_option opt ) const {
140     char *value;
141     checkOpt(opt, STRING);
142     ldap_get_option( m_ld, optmap[opt].optval, (void*) &value);
143     std::string strval;
144     if (value)
145     {
146         strval=std::string(value);
147         ldap_memfree(value);
148     }
149     return strval;
150 }
151
152 void TlsOptions::newCtx() const {
153     int val = 0;
154     int ret = ldap_set_option( m_ld, LDAP_OPT_X_TLS_NEWCTX, &val);
155     if ( ret != LDAP_OPT_SUCCESS )
156     {
157         if ( ret != LDAP_OPT_ERROR ){
158             throw( LDAPException( ret ));
159         } else {
160             throw( LDAPException( LDAP_LOCAL_ERROR, "error while renewing TLS context" ) );
161         }
162     }
163 }