]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/gss_context.hh
Merge branch 'ednssurg' of github.com:ahupowerdns/pdns into ednssurg
[thirdparty/pdns.git] / pdns / gss_context.hh
1 #ifndef GSS_CONTEXT_HH
2 #define GSS_CONTEXT_HH
3 #pragma once
4
5 #ifdef ENABLE_GSS_TSIG
6 #include <gssapi/gssapi.h>
7 #include <gssapi/gssapi_krb5.h>
8 #include <gssapi/gssapi_ext.h>
9 #endif
10
11 //! Generic errors
12 enum GssContextError {
13 GSS_CONTEXT_NO_ERROR,
14 GSS_CONTEXT_UNSUPPORTED,
15 GSS_CONTEXT_NOT_FOUND,
16 GSS_CONTEXT_NOT_INITIALIZED,
17 GSS_CONTEXT_INVALID,
18 GSS_CONTEXT_EXPIRED,
19 GSS_CONTEXT_ALREADY_INITIALIZED
20 };
21
22 //! GSS context types
23 enum GssContextType {
24 GSS_CONTEXT_NONE,
25 GSS_CONTEXT_INIT,
26 GSS_CONTEXT_ACCEPT
27 };
28
29 class GssSecContext;
30
31 /*! Class for representing GSS names, such as host/host.domain.com@REALM.
32 */
33 class GssName {
34 public:
35 //! Initialize to empty name
36 GssName() {
37 setName("");
38 };
39
40 //! Initilize using specific name
41 GssName(const std::string& name) {
42 setName(name);
43 };
44
45 //! Parse name into native representation
46 bool setName(const std::string& name) {
47 #ifdef ENABLE_GSS_TSIG
48 gss_buffer_desc buffer;
49 d_name = GSS_C_NO_NAME;
50
51 if (!name.empty()) {
52 buffer.length = name.size();
53 buffer.value = (void*)name.c_str();
54 d_maj = gss_import_name(&d_min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &d_name);
55 return d_maj == GSS_S_COMPLETE;
56 }
57
58 return true;
59 #endif
60 return false;
61 };
62
63 ~GssName() {
64 #ifdef ENABLE_GSS_TSIG
65 if (d_name != GSS_C_NO_NAME)
66 gss_release_name(&d_min, &d_name);
67 #endif
68 };
69
70 //! Compare two Gss Names, if no gss support is compiled in, returns false always
71 //! This is not necessarely same as string comparison between two non-parsed names
72 bool operator==(const GssName& rhs) {
73 #ifdef ENABLE_GSS_TSIG
74 OM_uint32 maj,min;
75 int result;
76 maj = gss_compare_name(&min, d_name, rhs.d_name, &result);
77 return (maj == GSS_S_COMPLETE && result != 0);
78 #endif
79 return false;
80 }
81
82 //! Compare two Gss Names, if no gss support is compiled in, returns false always
83 //! This is not necessarely same as string comparison between two non-parsed names
84 bool match(const std::string& name) {
85 #ifdef ENABLE_GSS_TSIG
86 OM_uint32 maj,min;
87 int result;
88 gss_name_t comp;
89 gss_buffer_desc buffer;
90 buffer.length = name.size();
91 buffer.value = (void*)name.c_str();
92 maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &comp);
93 if (maj != GSS_S_COMPLETE)
94 throw PDNSException("Could not import " + name + ": " + boost::lexical_cast<std::string>(maj) + string(",") + boost::lexical_cast<std::string>(min));
95 // do comparison
96 maj = gss_compare_name(&min, d_name, comp, &result);
97 gss_release_name(&min, &comp);
98 return (maj == GSS_S_COMPLETE && result != 0);
99 #else
100 return false;
101 #endif
102 };
103
104 //! Check if GSS name was parsed successfully.
105 bool valid() {
106 #ifdef ENABLE_GSS_TSIG
107 return d_maj == GSS_S_COMPLETE;
108 #else
109 return false;
110 #endif
111 }
112 private:
113 #ifdef ENABLE_GSS_TSIG
114 OM_uint32 d_maj,d_min;
115 gss_name_t d_name;
116 #endif
117 };
118
119 class GssContext {
120 public:
121 static bool supported(); //<! Returns true if GSS is supported in the first place
122 GssContext(); //<! Construct new GSS context with random name
123 GssContext(const std::string& label); //<! Create or open existing named context
124
125 void setLocalPrincipal(const std::string& name); //<! Set our gss name
126 bool getLocalPrincipal(std::string& name); //<! Get our name
127 void setPeerPrincipal(const std::string& name); //<! Set remote name (do not use after negotiation)
128 bool getPeerPrincipal(std::string &name); //<! Return remote name, returns actual name after negotatioan
129
130 void generateLabel(const std::string& suffix); //<! Generate random context name using suffix (such as mydomain.com)
131 void setLabel(const std::string& label); //<! Set context name to this label
132 const std::string& getLabel() { return d_label; } //<! Return context name
133
134 bool init(const std::string &input, std::string& output); //<! Perform GSS Initiate Security Context handshake
135 bool accept(const std::string &input, std::string& output); //<! Perform GSS Acccept Security Context handshake
136 bool destroy(); //<! Release the cached context
137 bool expired(); //<! Check if context is expired
138 bool valid(); //<! Check if context is valid
139
140 bool sign(const std::string &input, std::string& output); //<! Sign something using gss
141 bool verify(const std::string &input, const std::string &signature); //<! Validate gss signature with something
142
143 GssContextError getError(); //<! Get error
144 const std::vector<std::string> getErrorStrings() { return d_gss_errors; } //<! Get native error texts
145 private:
146 void release(); //<! Release context
147 void initialize(); //<! Initialize context
148 #ifdef ENABLE_GSS_TSIG
149 void processError(const string& method, OM_uint32 maj, OM_uint32 min); //<! Process and fill error text vector
150 #endif
151 std::string d_label; //<! Context name
152 std::string d_peerPrincipal; //<! Remote name
153 std::string d_localPrincipal; //<! Our name
154 GssContextError d_error; //<! Context error
155 GssContextType d_type; //<! Context type
156 std::vector<std::string> d_gss_errors; //<! Native error string(s)
157 boost::shared_ptr<GssSecContext> d_ctx; //<! Attached security context
158 };
159
160 bool gss_add_signature(const DNSName& context, const std::string& message, std::string& mac); //<! Create signature
161 bool gss_verify_signature(const DNSName& context, const std::string& message, const std::string& mac); //<! Validate signature
162
163 #endif