gssapi_server.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 
5 #ifdef HAVE_LIBGSSAPI_KRB5
6 
7 #include <string.h>
8 #include <string>
9 
10 #include "msg.hpp"
11 #include "session_base.hpp"
12 #include "err.hpp"
13 #include "gssapi_server.hpp"
14 #include "wire.hpp"
15 
16 #include <gssapi/gssapi.h>
17 
18 zmq::gssapi_server_t::gssapi_server_t (session_base_t *session_,
19  const std::string &peer_address_,
20  const options_t &options_) :
21  mechanism_base_t (session_, options_),
22  gssapi_mechanism_base_t (session_, options_),
23  zap_client_t (session_, peer_address_, options_),
24  session (session_),
25  peer_address (peer_address_),
26  state (recv_next_token),
27  security_context_established (false)
28 {
29  maj_stat = GSS_S_CONTINUE_NEEDED;
30  if (!options_.gss_principal.empty ()) {
31  const std::string::size_type principal_size =
32  options_.gss_principal.size ();
33  principal_name = static_cast<char *> (malloc (principal_size + 1));
34  assert (principal_name);
35  memcpy (principal_name, options_.gss_principal.c_str (),
36  principal_size + 1);
37  gss_OID name_type = convert_nametype (options_.gss_principal_nt);
38  if (acquire_credentials (principal_name, &cred, name_type) != 0)
39  maj_stat = GSS_S_FAILURE;
40  }
41 }
42 
43 zmq::gssapi_server_t::~gssapi_server_t ()
44 {
45  if (cred)
46  gss_release_cred (&min_stat, &cred);
47 
48  if (target_name)
49  gss_release_name (&min_stat, &target_name);
50 }
51 
52 int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_)
53 {
54  if (state == send_ready) {
55  int rc = produce_ready (msg_);
56  if (rc == 0)
57  state = recv_ready;
58 
59  return rc;
60  }
61 
62  if (state != send_next_token) {
63  errno = EAGAIN;
64  return -1;
65  }
66 
67  if (produce_next_token (msg_) < 0)
68  return -1;
69 
70  if (maj_stat != GSS_S_CONTINUE_NEEDED && maj_stat != GSS_S_COMPLETE)
71  return -1;
72 
73  if (maj_stat == GSS_S_COMPLETE) {
74  security_context_established = true;
75  }
76 
77  state = recv_next_token;
78 
79  return 0;
80 }
81 
82 int zmq::gssapi_server_t::process_handshake_command (msg_t *msg_)
83 {
84  if (state == recv_ready) {
85  int rc = process_ready (msg_);
86  if (rc == 0)
87  state = connected;
88 
89  return rc;
90  }
91 
92  if (state != recv_next_token) {
93  session->get_socket ()->event_handshake_failed_protocol (
94  session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND);
95  errno = EPROTO;
96  return -1;
97  }
98 
99  if (security_context_established) {
100  // Use ZAP protocol (RFC 27) to authenticate the user.
101  // Note that rc will be -1 only if ZAP is not set up, but if it was
102  // requested and it does not work properly the program will abort.
103  bool expecting_zap_reply = false;
104  int rc = session->zap_connect ();
105  if (rc == 0) {
106  send_zap_request ();
107  rc = receive_and_process_zap_reply ();
108  if (rc != 0) {
109  if (rc == -1)
110  return -1;
111  expecting_zap_reply = true;
112  }
113  }
114  state = expecting_zap_reply ? expect_zap_reply : send_ready;
115  return 0;
116  }
117 
118  if (process_next_token (msg_) < 0)
119  return -1;
120 
121  accept_context ();
122  state = send_next_token;
123 
124  errno_assert (msg_->close () == 0);
125  errno_assert (msg_->init () == 0);
126 
127  return 0;
128 }
129 
130 void zmq::gssapi_server_t::send_zap_request ()
131 {
132  gss_buffer_desc principal;
133  gss_display_name (&min_stat, target_name, &principal, NULL);
134  zap_client_t::send_zap_request (
135  "GSSAPI", 6, reinterpret_cast<const uint8_t *> (principal.value),
136  principal.length);
137 
138  gss_release_buffer (&min_stat, &principal);
139 }
140 
141 int zmq::gssapi_server_t::encode (msg_t *msg_)
142 {
143  zmq_assert (state == connected);
144 
145  if (do_encryption)
146  return encode_message (msg_);
147 
148  return 0;
149 }
150 
151 int zmq::gssapi_server_t::decode (msg_t *msg_)
152 {
153  zmq_assert (state == connected);
154 
155  if (do_encryption)
156  return decode_message (msg_);
157 
158  return 0;
159 }
160 
161 int zmq::gssapi_server_t::zap_msg_available ()
162 {
163  if (state != expect_zap_reply) {
164  errno = EFSM;
165  return -1;
166  }
167  const int rc = receive_and_process_zap_reply ();
168  if (rc == 0)
169  state = send_ready;
170  return rc == -1 ? -1 : 0;
171 }
172 
173 zmq::mechanism_t::status_t zmq::gssapi_server_t::status () const
174 {
175  return state == connected ? mechanism_t::ready : mechanism_t::handshaking;
176 }
177 
178 int zmq::gssapi_server_t::produce_next_token (msg_t *msg_)
179 {
180  if (send_tok.length != 0) { // Client expects another token
181  if (produce_initiate (msg_, send_tok.value, send_tok.length) < 0)
182  return -1;
183  gss_release_buffer (&min_stat, &send_tok);
184  }
185 
186  if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) {
187  gss_release_name (&min_stat, &target_name);
188  if (context != GSS_C_NO_CONTEXT)
189  gss_delete_sec_context (&min_stat, &context, GSS_C_NO_BUFFER);
190  return -1;
191  }
192 
193  return 0;
194 }
195 
196 int zmq::gssapi_server_t::process_next_token (msg_t *msg_)
197 {
198  if (maj_stat == GSS_S_CONTINUE_NEEDED) {
199  if (process_initiate (msg_, &recv_tok.value, recv_tok.length) < 0) {
200  if (target_name != GSS_C_NO_NAME)
201  gss_release_name (&min_stat, &target_name);
202  return -1;
203  }
204  }
205 
206  return 0;
207 }
208 
209 void zmq::gssapi_server_t::accept_context ()
210 {
211  maj_stat = gss_accept_sec_context (
212  &init_sec_min_stat, &context, cred, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS,
213  &target_name, &doid, &send_tok, &ret_flags, NULL, NULL);
214 
215  if (recv_tok.value) {
216  free (recv_tok.value);
217  recv_tok.value = NULL;
218  }
219 }
220 
221 #endif
NULL
NULL
Definition: test_security_zap.cpp:405
ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
#define ZMQ_PROTOCOL_ERROR_ZMTP_UNEXPECTED_COMMAND
Definition: zmq.h:425
EFSM
#define EFSM
Definition: zmq.h:159
EAGAIN
#define EAGAIN
Definition: errno.hpp:14
gssapi_server.hpp
precompiled.hpp
zmq_assert
#define zmq_assert(x)
Definition: err.hpp:102
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
errno
int errno
wire.hpp
EPROTO
#define EPROTO
Definition: err.hpp:26
errno_assert
#define errno_assert(x)
Definition: err.hpp:113
zmq::mechanism_t::status_t
status_t
Definition: mechanism.hpp:22
msg.hpp
err.hpp
session_base.hpp
false
#define false
Definition: cJSON.c:70
options_
DebugStringOptions options_
Definition: src/google/protobuf/descriptor.cc:2410


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:53