Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
L
libzmq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
libzmq
Commits
3c414c4a
Commit
3c414c4a
authored
Oct 08, 2013
by
Mike Gatny
Committed by
Chris Busbey
Apr 24, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
GSSAPI mechanism now fully working with encryption
parent
eb286252
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
299 additions
and
276 deletions
+299
-276
AUTHORS
AUTHORS
+1
-0
gssapi_client.cpp
src/gssapi_client.cpp
+60
-68
gssapi_client.hpp
src/gssapi_client.hpp
+11
-2
gssapi_mechanism_base.cpp
src/gssapi_mechanism_base.cpp
+127
-103
gssapi_mechanism_base.hpp
src/gssapi_mechanism_base.hpp
+37
-23
gssapi_server.cpp
src/gssapi_server.cpp
+52
-75
gssapi_server.hpp
src/gssapi_server.hpp
+11
-5
No files found.
AUTHORS
View file @
3c414c4a
...
...
@@ -69,6 +69,7 @@ McClain Looney <m@loonsoft.com>
Michael Compton <michael.compton@littleedge.co.uk>
Mika Fischer <mika.fischer@zoopnet.de>
Mikael Helbo Kjaer <mhk@designtech.dk>
Mike Gatny <mgatny@gmail.com>
Mikko Koppanen <mkoppanen@php.net>
Min Ragan-Kelley <benjaminrk@gmail.com>
Neale Ferguson <neale@sinenomine.net>
...
...
src/gssapi_client.cpp
View file @
3c414c4a
...
...
@@ -34,13 +34,13 @@
zmq
::
gssapi_client_t
::
gssapi_client_t
(
const
options_t
&
options_
)
:
gssapi_mechanism_base_t
(),
mechanism_t
(
options_
),
state
(
send_next_token
),
state
(
call_next_init
),
token_ptr
(
GSS_C_NO_BUFFER
),
mechs
(),
security_context_established
(
false
)
{
maj_stat
=
GSS_S_COMPLETE
;
service_name
=
strdup
(
"host"
);
//
/ FIXME
add service_name to options
service_name
=
strdup
(
"host"
);
//
TODO:
add service_name to options
mechs
.
elements
=
NULL
;
mechs
.
count
=
0
;
}
...
...
@@ -49,80 +49,80 @@ zmq::gssapi_client_t::~gssapi_client_t ()
{
if
(
service_name
)
free
(
service_name
);
/// FIXME release this or not?
if
(
cred
)
gss_release_cred
(
&
min_stat
,
&
cred
);
}
int
zmq
::
gssapi_client_t
::
next_handshake_command
(
msg_t
*
msg_
)
{
int
rc
=
0
;
switch
(
state
)
{
case
send_next_token
:
rc
=
produce_next_token
(
msg_
);
if
(
rc
==
0
)
state
=
recv_next_token
;
break
;
case
almost_ready
:
state
=
ready
;
break
;
default
:
errno
=
EAGAIN
;
rc
=
-
1
;
break
;
if
(
security_context_established
)
{
state
=
connected
;
return
0
;
}
return
rc
;
if
(
state
!=
call_next_init
)
{
errno
=
EAGAIN
;
return
-
1
;
}
if
(
initialize_context
()
<
0
)
return
-
1
;
if
(
produce_next_token
(
msg_
)
<
0
)
return
-
1
;
if
(
maj_stat
!=
GSS_S_CONTINUE_NEEDED
&&
maj_stat
!=
GSS_S_COMPLETE
)
return
-
1
;
if
(
maj_stat
==
GSS_S_COMPLETE
)
security_context_established
=
true
;
else
state
=
recv_next_token
;
return
0
;
}
int
zmq
::
gssapi_client_t
::
process_handshake_command
(
msg_t
*
msg_
)
{
int
rc
=
0
;
switch
(
state
)
{
case
recv_next_token
:
rc
=
process_next_token
(
msg_
);
if
(
rc
==
0
)
state
=
security_context_established
?
almost_ready
:
send_next_token
;
break
;
case
almost_ready
:
state
=
ready
;
break
;
default
:
errno
=
EPROTO
;
rc
=
-
1
;
break
;
}
if
(
rc
==
0
)
{
rc
=
msg_
->
close
();
errno_assert
(
rc
==
0
);
rc
=
msg_
->
init
();
errno_assert
(
rc
==
0
);
if
(
state
!=
recv_next_token
)
{
errno
=
EPROTO
;
return
-
1
;
}
return
rc
;
if
(
process_next_token
(
msg_
)
<
0
)
return
-
1
;
if
(
maj_stat
==
GSS_S_COMPLETE
)
security_context_established
=
true
;
else
if
(
maj_stat
==
GSS_S_CONTINUE_NEEDED
)
state
=
call_next_init
;
else
return
-
1
;
errno_assert
(
msg_
->
close
()
==
0
);
errno_assert
(
msg_
->
init
()
==
0
);
return
0
;
}
int
zmq
::
gssapi_client_t
::
encode
(
msg_t
*
msg_
)
{
int
rc
=
0
;
zmq_assert
(
state
==
ready
);
return
rc
;
zmq_assert
(
state
==
connected
);
return
encode_message
(
msg_
);
}
int
zmq
::
gssapi_client_t
::
decode
(
msg_t
*
msg_
)
{
int
rc
=
0
;
zmq_assert
(
state
==
ready
);
return
rc
;
zmq_assert
(
state
==
connected
);
return
decode_message
(
msg_
);
}
bool
zmq
::
gssapi_client_t
::
is_handshake_complete
()
const
{
fprintf
(
stderr
,
"%s:%d: is_handshake_complete=%d, security_context_established=%d
\n
"
,
__FILE__
,
__LINE__
,
(
state
==
ready
),
security_context_established
);
/// FIXME remove
return
state
==
ready
;
return
state
==
connected
;
}
int
zmq
::
gssapi_client_t
::
produce_next_token
(
msg_t
*
msg_
)
int
zmq
::
gssapi_client_t
::
initialize_context
(
)
{
// First time through, import service_name into target_name
if
(
target_name
==
GSS_C_NO_NAME
)
{
...
...
@@ -131,10 +131,8 @@ int zmq::gssapi_client_t::produce_next_token (msg_t *msg_)
OM_uint32
maj
=
gss_import_name
(
&
min_stat
,
&
send_tok
,
gss_nt_service_name
,
&
target_name
);
if
(
maj
!=
GSS_S_COMPLETE
)
{
fprintf
(
stderr
,
"%s:%d: failed to import service name
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("parsing name", maj_stat, min_stat);
if
(
maj
!=
GSS_S_COMPLETE
)
return
-
1
;
}
}
maj_stat
=
gss_init_sec_context
(
&
init_sec_min_stat
,
cred
,
&
context
,
...
...
@@ -144,22 +142,22 @@ int zmq::gssapi_client_t::produce_next_token (msg_t *msg_)
if
(
token_ptr
!=
GSS_C_NO_BUFFER
)
free
(
recv_tok
.
value
);
if
(
send_tok
.
length
!=
0
)
{
// server expects another token
fprintf
(
stderr
,
"%s:%d: producing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("parsing name", maj_stat, min_stat);
if
(
produce_token
(
msg_
,
TOKEN_CONTEXT
,
send_tok
.
value
,
send_tok
.
length
)
<
0
)
{
return
0
;
}
int
zmq
::
gssapi_client_t
::
produce_next_token
(
msg_t
*
msg_
)
{
if
(
send_tok
.
length
!=
0
)
{
// Server expects another token
if
(
produce_initiate
(
msg_
,
send_tok
.
value
,
send_tok
.
length
)
<
0
)
{
gss_release_buffer
(
&
min_stat
,
&
send_tok
);
gss_release_name
(
&
min_stat
,
&
target_name
);
return
-
1
;
}
}
else
fprintf
(
stderr
,
"%s:%d: skip producing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("parsing name", maj_stat, min_stat);
gss_release_buffer
(
&
min_stat
,
&
send_tok
);
if
(
maj_stat
!=
GSS_S_COMPLETE
&&
maj_stat
!=
GSS_S_CONTINUE_NEEDED
)
{
fprintf
(
stderr
,
"%s:%d: failed to create GSSAPI security context
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat);
gss_release_name
(
&
min_stat
,
&
target_name
);
if
(
context
!=
GSS_C_NO_CONTEXT
)
gss_delete_sec_context
(
&
min_stat
,
&
context
,
GSS_C_NO_BUFFER
);
...
...
@@ -172,18 +170,12 @@ int zmq::gssapi_client_t::produce_next_token (msg_t *msg_)
int
zmq
::
gssapi_client_t
::
process_next_token
(
msg_t
*
msg_
)
{
if
(
maj_stat
==
GSS_S_CONTINUE_NEEDED
)
{
fprintf
(
stderr
,
"%s:%d: processing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("parsing name", maj_stat, min_stat);
if
(
process_token
(
msg_
,
token_flags
,
&
recv_tok
.
value
,
recv_tok
.
length
)
<
0
)
{
if
(
process_initiate
(
msg_
,
&
recv_tok
.
value
,
recv_tok
.
length
)
<
0
)
{
gss_release_name
(
&
min_stat
,
&
target_name
);
return
-
1
;
}
token_ptr
=
&
recv_tok
;
}
else
fprintf
(
stderr
,
"%s:%d: skip processing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("parsing name", maj_stat, min_stat);
if
(
maj_stat
==
GSS_S_COMPLETE
)
security_context_established
=
true
;
return
0
;
}
...
...
src/gssapi_client.hpp
View file @
3c414c4a
...
...
@@ -48,17 +48,26 @@ namespace zmq
private
:
enum
state_t
{
call_next_init
,
send_next_token
,
recv_next_token
,
almost_ready
,
ready
connected
};
// Current FSM state
state_t
state
;
// Points to either send_tok or recv_tok
// during context initialization
gss_buffer_desc
*
token_ptr
;
// The desired underlying mechanism
gss_OID_set_desc
mechs
;
// True iff client considers the server authenticated
bool
security_context_established
;
int
initialize_context
();
int
produce_next_token
(
msg_t
*
msg_
);
int
process_next_token
(
msg_t
*
msg_
);
};
...
...
src/gssapi_mechanism_base.cpp
View file @
3c414c4a
...
...
@@ -34,7 +34,7 @@
zmq
::
gssapi_mechanism_base_t
::
gssapi_mechanism_base_t
()
:
send_tok
(),
recv_tok
(),
in_buf
(),
/// FIXME remove?
in_buf (),
target_name
(
GSS_C_NO_NAME
),
service_name
(
NULL
),
maj_stat
(
GSS_S_COMPLETE
),
...
...
@@ -42,7 +42,6 @@ zmq::gssapi_mechanism_base_t::gssapi_mechanism_base_t () :
init_sec_min_stat
(
0
),
ret_flags
(
0
),
gss_flags
(
GSS_C_MUTUAL_FLAG
|
GSS_C_REPLAY_FLAG
),
token_flags
(
0
),
cred
(
GSS_C_NO_CREDENTIAL
),
context
(
GSS_C_NO_CONTEXT
)
{
...
...
@@ -56,87 +55,106 @@ zmq::gssapi_mechanism_base_t::~gssapi_mechanism_base_t ()
gss_delete_sec_context
(
&
min_stat
,
&
context
,
GSS_C_NO_BUFFER
);
}
int
zmq
::
gssapi_mechanism_base_t
::
produce_token
(
msg_t
*
msg_
,
int
flags_
,
void
*
token_value_
,
size_t
token_length
_
)
int
zmq
::
gssapi_mechanism_base_t
::
encode_message
(
msg_t
*
msg
_
)
{
zmq_assert
(
token_value_
);
zmq_assert
(
token_length_
<=
0xFFFFFFFFUL
);
const
size_t
cmd_len
=
6
+
1
+
4
+
token_length_
;
uint8_t
*
cmd_buf
=
static_cast
<
uint8_t
*>
(
malloc
(
cmd_len
));
alloc_assert
(
cmd_buf
);
// Wrap the token value
int
state
;
gss_buffer_desc
plaintext
;
gss_buffer_desc
wrapped
;
plaintext
.
value
=
msg_
->
data
();
plaintext
.
length
=
msg_
->
size
();
maj_stat
=
gss_wrap
(
&
min_stat
,
context
,
1
,
GSS_C_QOP_DEFAULT
,
&
plaintext
,
&
state
,
&
wrapped
);
zmq_assert
(
maj_stat
==
GSS_S_COMPLETE
);
zmq_assert
(
state
);
uint8_t
*
ptr
=
cmd_buf
;
// Re-initialize msg_ for wrapped text
int
rc
=
msg_
->
close
();
zmq_assert
(
rc
==
0
);
// Add command name
memcpy
(
ptr
,
"
\x05
TOKEN"
,
6
);
ptr
+=
6
;
rc
=
msg_
->
init_size
(
8
+
4
+
wrapped
.
length
);
zmq_assert
(
rc
==
0
);
// Add gss flags
put_uint8
(
ptr
,
static_cast
<
uint8_t
>
(
flags_
));
ptr
+=
1
;
uint8_t
*
ptr
=
static_cast
<
uint8_t
*>
(
msg_
->
data
());
// Add command string
memcpy
(
ptr
,
"
\x07
MESSAGE"
,
8
);
ptr
+=
8
;
// Add token length
put_uint32
(
ptr
,
static_cast
<
uint32_t
>
(
token_length_
));
put_uint32
(
ptr
,
static_cast
<
uint32_t
>
(
wrapped
.
length
));
ptr
+=
4
;
// Add token value
memcpy
(
ptr
,
token_value_
,
token_length_
);
ptr
+=
token_length_
;
// Add
wrapped
token value
memcpy
(
ptr
,
wrapped
.
value
,
wrapped
.
length
);
ptr
+=
wrapped
.
length
;
const
int
rc
=
msg_
->
init_size
(
cmd_len
);
errno_assert
(
rc
==
0
);
memcpy
(
msg_
->
data
(),
cmd_buf
,
cmd_len
);
free
(
cmd_buf
);
gss_release_buffer
(
&
min_stat
,
&
wrapped
);
return
0
;
}
int
zmq
::
gssapi_mechanism_base_t
::
process_token
(
msg_t
*
msg_
,
int
&
flags_
,
void
**
token_value_
,
size_t
&
token_length
_
)
int
zmq
::
gssapi_mechanism_base_t
::
decode_message
(
msg_t
*
msg
_
)
{
zmq_assert
(
token_value_
);
uint8_t
*
ptr
=
static_cast
<
uint8_t
*>
(
msg_
->
data
());
const
uint8_t
*
ptr
=
static_cast
<
uint8_t
*>
(
msg_
->
data
());
size_t
bytes_left
=
msg_
->
size
();
// Get command name
if
(
bytes_left
<
6
||
memcmp
(
ptr
,
"
\x05
TOKEN"
,
6
))
{
errno
=
EPROTO
;
return
-
1
;
}
ptr
+=
6
;
bytes_left
-=
6
;
// Get flags
if
(
bytes_left
<
1
)
{
// Get command string
if
(
bytes_left
<
8
||
memcmp
(
ptr
,
"
\x07
MESSAGE"
,
8
))
{
errno
=
EPROTO
;
return
-
1
;
}
flags_
=
static_cast
<
int
>
(
get_uint8
(
ptr
));
ptr
+=
1
;
bytes_left
-=
1
;
ptr
+=
8
;
bytes_left
-=
8
;
// Get token length
if
(
bytes_left
<
4
)
{
errno
=
EPROTO
;
return
-
1
;
}
token_length_
=
get_uint32
(
ptr
);
gss_buffer_desc
wrapped
;
wrapped
.
length
=
get_uint32
(
ptr
);
ptr
+=
4
;
bytes_left
-=
4
;
// Get token value
. TODO do unwrap here to prevent this extra memcpy.
if
(
bytes_left
<
token_length_
)
{
// Get token value
if
(
bytes_left
<
wrapped
.
length
)
{
errno
=
EPROTO
;
return
-
1
;
}
*
token_value_
=
static_cast
<
char
*>
(
malloc
(
token_length_
?
token_length_
:
1
));
if
(
token_length_
)
{
alloc_assert
(
*
token_value_
);
memcpy
(
*
token_value_
,
ptr
,
token_length_
);
ptr
+=
token_length_
;
bytes_left
-=
token_length_
;
// TODO: instead of malloc/memcpy, can we just do: wrapped.value = ptr;
const
size_t
alloc_length
=
wrapped
.
length
?
wrapped
.
length
:
1
;
wrapped
.
value
=
static_cast
<
char
*>
(
malloc
(
alloc_length
));
if
(
wrapped
.
length
)
{
alloc_assert
(
wrapped
.
value
);
memcpy
(
wrapped
.
value
,
ptr
,
wrapped
.
length
);
ptr
+=
wrapped
.
length
;
bytes_left
-=
wrapped
.
length
;
}
// Unwrap the token value
int
state
;
gss_buffer_desc
plaintext
;
maj_stat
=
gss_unwrap
(
&
min_stat
,
context
,
&
wrapped
,
&
plaintext
,
&
state
,
(
gss_qop_t
*
)
NULL
);
zmq_assert
(
maj_stat
==
GSS_S_COMPLETE
);
zmq_assert
(
state
);
// Re-initialize msg_ for plaintext
int
rc
=
msg_
->
close
();
zmq_assert
(
rc
==
0
);
rc
=
msg_
->
init_size
(
plaintext
.
length
);
zmq_assert
(
rc
==
0
);
memcpy
(
msg_
->
data
(),
plaintext
.
value
,
plaintext
.
length
);
gss_release_buffer
(
&
min_stat
,
&
plaintext
);
gss_release_buffer
(
&
min_stat
,
&
wrapped
);
if
(
bytes_left
>
0
)
{
errno
=
EPROTO
;
return
-
1
;
...
...
@@ -145,69 +163,75 @@ int zmq::gssapi_mechanism_base_t::process_token (msg_t *msg_, int &flags_, void
return
0
;
}
/// TODO add support for TOKEN_SEND_MIC
/// TODO use gss_wrap_size_limit
int
zmq
::
gssapi_mechanism_base_t
::
produce_message
(
msg_t
*
msg_
)
int
zmq
::
gssapi_mechanism_base_t
::
produce_initiate
(
msg_t
*
msg_
,
void
*
token_value_
,
size_t
token_length_
)
{
// wrap it
int
state
;
gss_buffer_desc
plaintext
;
gss_buffer_desc
wrapped
;
plaintext
.
value
=
msg_
->
data
();
plaintext
.
length
=
msg_
->
size
();
maj_stat
=
gss_wrap
(
&
min_stat
,
context
,
1
,
GSS_C_QOP_DEFAULT
,
&
plaintext
,
&
state
,
&
wrapped
);
zmq_assert
(
maj_stat
==
GSS_S_COMPLETE
);
zmq_assert
(
state
);
zmq_assert
(
token_value_
);
zmq_assert
(
token_length_
<=
0xFFFFFFFFUL
);
// prepare msg_ for wrapped text
int
rc
=
msg_
->
close
();
zmq_assert
(
rc
==
0
);
const
size_t
command_size
=
9
+
4
+
token_length_
;
// produce token
const
int
flags
=
(
TOKEN_DATA
|
TOKEN_WRAPPED
|
TOKEN_ENCRYPTED
);
rc
=
produce_token
(
msg_
,
flags
,
wrapped
.
value
,
wrapped
.
length
);
zmq_assert
(
rc
==
0
);
gss_release_buffer
(
&
min_stat
,
&
wrapped
);
const
int
rc
=
msg_
->
init_size
(
command_size
);
errno_assert
(
rc
==
0
);
uint8_t
*
ptr
=
static_cast
<
uint8_t
*>
(
msg_
->
data
());
// Add command string
memcpy
(
ptr
,
"
\x08
INITIATE"
,
9
);
ptr
+=
9
;
// Add token length
put_uint32
(
ptr
,
static_cast
<
uint32_t
>
(
token_length_
));
ptr
+=
4
;
// Add token value
memcpy
(
ptr
,
token_value_
,
token_length_
);
ptr
+=
token_length_
;
return
0
;
}
int
zmq
::
gssapi_mechanism_base_t
::
process_message
(
msg_t
*
msg_
)
int
zmq
::
gssapi_mechanism_base_t
::
process_initiate
(
msg_t
*
msg_
,
void
**
token_value_
,
size_t
&
token_length_
)
{
// process token
int
flags
;
gss_buffer_desc
wrapped
;
int
rc
=
process_token
(
msg_
,
flags
,
&
wrapped
.
value
,
wrapped
.
length
);
zmq_assert
(
rc
==
0
);
// ensure valid security context
zmq_assert
(
context
!=
GSS_C_NO_CONTEXT
);
zmq_assert
(
flags
&
TOKEN_WRAPPED
);
zmq_assert
(
flags
&
TOKEN_ENCRYPTED
);
// unwrap
int
state
;
gss_buffer_desc
plaintext
;
maj_stat
=
gss_unwrap
(
&
min_stat
,
context
,
&
wrapped
,
&
plaintext
,
&
state
,
(
gss_qop_t
*
)
NULL
);
zmq_assert
(
token_value_
);
const
uint8_t
*
ptr
=
static_cast
<
uint8_t
*>
(
msg_
->
data
());
size_t
bytes_left
=
msg_
->
size
();
zmq_assert
(
maj_stat
==
GSS_S_COMPLETE
);
zmq_assert
(
state
);
// Get command string
if
(
bytes_left
<
9
||
memcmp
(
ptr
,
"
\x08
INITIATE"
,
9
))
{
errno
=
EPROTO
;
return
-
1
;
}
ptr
+=
9
;
bytes_left
-=
9
;
// re-init msg_ with plaintext
rc
=
msg_
->
close
();
zmq_assert
(
rc
==
0
);
msg_
->
init_size
(
plaintext
.
length
);
zmq_assert
(
rc
==
0
);
// Get token length
if
(
bytes_left
<
4
)
{
errno
=
EPROTO
;
return
-
1
;
}
token_length_
=
get_uint32
(
ptr
);
ptr
+=
4
;
bytes_left
-=
4
;
memcpy
(
msg_
->
data
(),
plaintext
.
value
,
plaintext
.
length
);
gss_release_buffer
(
&
min_stat
,
&
plaintext
);
gss_release_buffer
(
&
min_stat
,
&
wrapped
);
// Get token value
if
(
bytes_left
<
token_length_
)
{
errno
=
EPROTO
;
return
-
1
;
}
*
token_value_
=
static_cast
<
char
*>
(
malloc
(
token_length_
?
token_length_
:
1
));
if
(
token_length_
)
{
alloc_assert
(
*
token_value_
);
memcpy
(
*
token_value_
,
ptr
,
token_length_
);
ptr
+=
token_length_
;
bytes_left
-=
token_length_
;
}
if
(
bytes_left
>
0
)
{
errno
=
EPROTO
;
return
-
1
;
}
return
0
;
}
...
...
src/gssapi_mechanism_base.hpp
View file @
3c414c4a
...
...
@@ -29,8 +29,9 @@ namespace zmq
class
msg_t
;
/// Both gssapi_server and gssapi_client need to produce and process
/// GSSAPI tokens. Common implementation is captured here.
/// Commonalities between clients and servers are captured here.
/// For example, clients and server both need to produce and
/// process INITIATE and MESSAGE commands.
class
gssapi_mechanism_base_t
{
public
:
...
...
@@ -38,42 +39,55 @@ namespace zmq
virtual
~
gssapi_mechanism_base_t
()
=
0
;
protected
:
/// Produce a
security context initialization toke
n
int
produce_
token
(
msg_t
*
msg_
,
int
flags_
,
void
*
token_value_
,
size_t
token_length
_
);
/// Process a
security context initialization toke
n
int
process_
token
(
msg_t
*
msg_
,
int
&
flags_
,
void
**
token_value_
,
size_t
&
token_length
_
);
///
Produce a wrapped message
using the established security context
int
produc
e_message
(
msg_t
*
msg_
);
///
Process a wrapped message
using the established security context
int
process
_message
(
msg_t
*
msg_
);
/// Produce a
n INITIATE during security context initializatio
n
int
produce_
initiate
(
msg_t
*
msg_
,
void
*
data_
,
size_t
data_len
_
);
/// Process a
n INITIATE during security context initializatio
n
int
process_
initiate
(
msg_t
*
msg_
,
void
**
data_
,
size_t
&
data_len
_
);
///
Encode a MESSAGE
using the established security context
int
encod
e_message
(
msg_t
*
msg_
);
///
Decode a MESSAGE
using the established security context
int
decode
_message
(
msg_t
*
msg_
);
/// Acquire security context credentials
static
int
acquire_credentials
(
char
*
service_name_
,
gss_cred_id_t
*
cred_
);
static
int
acquire_credentials
(
char
*
service_name_
,
gss_cred_id_t
*
cred_
);
protected
:
const
static
int
TOKEN_NOOP
=
(
1
<<
0
);
const
static
int
TOKEN_CONTEXT
=
(
1
<<
1
);
const
static
int
TOKEN_DATA
=
(
1
<<
2
);
const
static
int
TOKEN_MIC
=
(
1
<<
3
);
const
static
int
TOKEN_CONTEXT_NEXT
=
(
1
<<
4
);
const
static
int
TOKEN_WRAPPED
=
(
1
<<
5
);
const
static
int
TOKEN_ENCRYPTED
=
(
1
<<
6
);
const
static
int
TOKEN_SEND_MIC
=
(
1
<<
7
);
/// Opaque GSSAPI token for outgoing data
gss_buffer_desc
send_tok
;
/// Opaque GSSAPI token for incoming data
gss_buffer_desc
recv_tok
;
gss_buffer_desc
in_buf
;
/// Opaque GSSAPI representation of service_name
gss_name_t
target_name
;
/// Human-readable service principal name
char
*
service_name
;
/// Status code returned by GSSAPI functions
OM_uint32
maj_stat
;
/// Status code returned by the underlying mechanism
OM_uint32
min_stat
;
/// Status code returned by the underlying mechanism
/// during context initialization
OM_uint32
init_sec_min_stat
;
/// Flags returned by GSSAPI (ignored)
OM_uint32
ret_flags
;
/// Flags returned by GSSAPI (ignored)
OM_uint32
gss_flags
;
int
token_flags
;
/// Credentials used to establish security context
gss_cred_id_t
cred
;
/// Opaque GSSAPI representation of the security context
gss_ctx_id_t
context
;
};
}
#endif
src/gssapi_server.cpp
View file @
3c414c4a
...
...
@@ -41,16 +41,12 @@ zmq::gssapi_server_t::gssapi_server_t (session_base_t *session_,
state
(
recv_next_token
),
security_context_established
(
false
)
{
service_name
=
(
char
*
)
"host"
;
/// FIXME add service_name to options
int
rc
=
acquire_credentials
(
service_name
,
&
cred
);
/// FIXME add creds to options too?
if
(
rc
==
0
)
{
fprintf
(
stderr
,
"%s:%d: acquire creds successful
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME remove
service_name
=
(
char
*
)
"host"
;
// TODO: add service_name to options
int
rc
=
acquire_credentials
(
service_name
,
&
cred
);
// TODO: add creds to options too?
if
(
rc
==
0
)
maj_stat
=
GSS_S_CONTINUE_NEEDED
;
}
else
{
fprintf
(
stderr
,
"%s:%d: acquire creds failed
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME remove
else
maj_stat
=
GSS_S_FAILURE
;
}
}
zmq
::
gssapi_server_t
::~
gssapi_server_t
()
...
...
@@ -61,64 +57,58 @@ zmq::gssapi_server_t::~gssapi_server_t ()
int
zmq
::
gssapi_server_t
::
next_handshake_command
(
msg_t
*
msg_
)
{
int
rc
=
0
;
switch
(
state
)
{
case
send_next_token
:
rc
=
produce_next_token
(
msg_
);
if
(
rc
==
0
)
state
=
security_context_established
?
almost_ready
:
recv_next_token
;
break
;
case
almost_ready
:
state
=
ready
;
break
;
default
:
errno
=
EPROTO
;
rc
=
-
1
;
break
;
if
(
state
!=
send_next_token
)
{
errno
=
EAGAIN
;
return
-
1
;
}
if
(
produce_next_token
(
msg_
)
<
0
)
return
-
1
;
if
(
maj_stat
!=
GSS_S_CONTINUE_NEEDED
&&
maj_stat
!=
GSS_S_COMPLETE
)
return
-
1
;
if
(
maj_stat
==
GSS_S_COMPLETE
)
{
gss_release_name
(
&
min_stat
,
&
target_name
);
security_context_established
=
true
;
state
=
connected
;
}
else
{
state
=
recv_next_token
;
}
return
rc
;
return
0
;
}
int
zmq
::
gssapi_server_t
::
process_handshake_command
(
msg_t
*
msg_
)
{
int
rc
=
0
;
switch
(
state
)
{
case
recv_next_token
:
rc
=
process_next_token
(
msg_
);
if
(
rc
==
0
)
state
=
send_next_token
;
break
;
case
almost_ready
:
state
=
ready
;
break
;
default
:
errno
=
EAGAIN
;
rc
=
-
1
;
break
;
}
if
(
rc
==
0
)
{
rc
=
msg_
->
close
();
errno_assert
(
rc
==
0
);
rc
=
msg_
->
init
();
errno_assert
(
rc
==
0
);
if
(
state
!=
recv_next_token
)
{
errno
=
EPROTO
;
return
-
1
;
}
return
rc
;
if
(
process_next_token
(
msg_
)
<
0
)
return
-
1
;
accept_context
();
state
=
send_next_token
;
errno_assert
(
msg_
->
close
()
==
0
);
errno_assert
(
msg_
->
init
()
==
0
);
return
0
;
}
int
zmq
::
gssapi_server_t
::
encode
(
msg_t
*
msg_
)
{
int
rc
=
0
;
zmq_assert
(
state
==
ready
);
return
rc
;
zmq_assert
(
state
==
connected
);
return
encode_message
(
msg_
);
}
int
zmq
::
gssapi_server_t
::
decode
(
msg_t
*
msg_
)
{
int
rc
=
0
;
zmq_assert
(
state
==
ready
);
return
rc
;
zmq_assert
(
state
==
connected
);
return
decode_message
(
msg_
);
}
int
zmq
::
gssapi_server_t
::
zap_msg_available
()
...
...
@@ -128,53 +118,42 @@ int zmq::gssapi_server_t::zap_msg_available ()
bool
zmq
::
gssapi_server_t
::
is_handshake_complete
()
const
{
fprintf
(
stderr
,
"%s:%d: is_handshake_complete=%d
\n
"
,
__FILE__
,
__LINE__
,
(
state
==
ready
));
/// FIXME remove
return
state
==
ready
;
return
state
==
connected
;
}
int
zmq
::
gssapi_server_t
::
produce_next_token
(
msg_t
*
msg_
)
{
if
(
send_tok
.
length
!=
0
)
{
// client expects another token
fprintf
(
stderr
,
"%s:%d: producing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
if
(
produce_token
(
msg_
,
TOKEN_CONTEXT
,
send_tok
.
value
,
send_tok
.
length
)
<
0
)
{
fprintf
(
stderr
,
"%s:%d: failed to produce token!
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
if
(
send_tok
.
length
!=
0
)
{
// Client expects another token
if
(
produce_initiate
(
msg_
,
send_tok
.
value
,
send_tok
.
length
)
<
0
)
return
-
1
;
}
gss_release_buffer
(
&
min_stat
,
&
send_tok
);
}
else
fprintf
(
stderr
,
"%s:%d: skip producing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
if
(
maj_stat
!=
GSS_S_COMPLETE
&&
maj_stat
!=
GSS_S_CONTINUE_NEEDED
)
{
fprintf
(
stderr
,
"%s:%d: failed to create GSSAPI security context
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
gss_release_name
(
&
min_stat
,
&
target_name
);
if
(
context
!=
GSS_C_NO_CONTEXT
)
gss_delete_sec_context
(
&
min_stat
,
&
context
,
GSS_C_NO_BUFFER
);
return
-
1
;
}
if
(
maj_stat
==
GSS_S_COMPLETE
)
{
gss_release_name
(
&
min_stat
,
&
target_name
);
security_context_established
=
true
;
}
return
0
;
}
int
zmq
::
gssapi_server_t
::
process_next_token
(
msg_t
*
msg_
)
{
if
(
maj_stat
==
GSS_S_CONTINUE_NEEDED
)
{
fprintf
(
stderr
,
"%s:%d: processing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
if
(
process_token
(
msg_
,
token_flags
,
&
recv_tok
.
value
,
recv_tok
.
length
)
<
0
)
{
if
(
process_initiate
(
msg_
,
&
recv_tok
.
value
,
recv_tok
.
length
)
<
0
)
{
if
(
target_name
!=
GSS_C_NO_NAME
)
gss_release_name
(
&
min_stat
,
&
target_name
);
fprintf
(
stderr
,
"%s:%d: failed to process token!
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
return
-
1
;
}
}
else
fprintf
(
stderr
,
"%s:%d: skip processing token
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME die("creating context", maj_stat, init_sec_min_stat); /// FIXME die("creating context", maj_stat, init_sec_min_stat);
return
0
;
}
void
zmq
::
gssapi_server_t
::
accept_context
()
{
maj_stat
=
gss_accept_sec_context
(
&
init_sec_min_stat
,
&
context
,
cred
,
&
recv_tok
,
GSS_C_NO_CHANNEL_BINDINGS
,
&
target_name
,
&
doid
,
&
send_tok
,
...
...
@@ -184,7 +163,5 @@ int zmq::gssapi_server_t::process_next_token (msg_t *msg_)
free
(
recv_tok
.
value
);
recv_tok
.
value
=
NULL
;
}
return
0
;
}
src/gssapi_server.hpp
View file @
3c414c4a
...
...
@@ -54,19 +54,25 @@ namespace zmq
enum
state_t
{
send_next_token
,
recv_next_token
,
waiting_for_zap_reply
,
almost_ready
,
ready
connected
};
session_base_t
*
const
session
;
const
std
::
string
peer_address
;
// Current FSM state
state_t
state
;
// True iff server considers the client authenticated
bool
security_context_established
;
// The underlying mechanism type (ignored)
gss_OID
doid
;
int
produce_next_token
(
msg_t
*
msg_
);
int
process_next_token
(
msg_t
*
msg_
);
void
accept_context
();
int
produce_next_token
(
msg_t
*
msg_
);
int
process_next_token
(
msg_t
*
msg_
);
};
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment