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
1445516c
Commit
1445516c
authored
Oct 03, 2013
by
Mike Gatny
Committed by
Chris Busbey
Apr 24, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Establishing GSSAPI sec context is working now
parent
6290ba16
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
232 additions
and
426 deletions
+232
-426
configure.ac
configure.ac
+1
-0
gssapi_client.cpp
src/gssapi_client.cpp
+75
-105
gssapi_client.hpp
src/gssapi_client.hpp
+8
-11
gssapi_mechanism_base.cpp
src/gssapi_mechanism_base.cpp
+46
-1
gssapi_mechanism_base.hpp
src/gssapi_mechanism_base.hpp
+25
-0
gssapi_server.cpp
src/gssapi_server.cpp
+70
-289
gssapi_server.hpp
src/gssapi_server.hpp
+7
-20
No files found.
configure.ac
View file @
1445516c
...
@@ -305,6 +305,7 @@ else
...
@@ -305,6 +305,7 @@ else
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
fi
fi
AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context],,AC_MSG_WARN(libgssapi_krb5 is needed for GSSAPI security))
#
#
# Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec
# Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec
...
...
src/gssapi_client.cpp
View file @
1445516c
...
@@ -34,12 +34,24 @@
...
@@ -34,12 +34,24 @@
zmq
::
gssapi_client_t
::
gssapi_client_t
(
const
options_t
&
options_
)
:
zmq
::
gssapi_client_t
::
gssapi_client_t
(
const
options_t
&
options_
)
:
gssapi_mechanism_base_t
(),
gssapi_mechanism_base_t
(),
mechanism_t
(
options_
),
mechanism_t
(
options_
),
state
(
sending_hello
)
state
(
send_next_token
),
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
mechs
.
elements
=
NULL
;
mechs
.
count
=
0
;
}
}
zmq
::
gssapi_client_t
::~
gssapi_client_t
()
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
zmq
::
gssapi_client_t
::
next_handshake_command
(
msg_t
*
msg_
)
...
@@ -47,24 +59,18 @@ int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_)
...
@@ -47,24 +59,18 @@ int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_)
int
rc
=
0
;
int
rc
=
0
;
switch
(
state
)
{
switch
(
state
)
{
case
send
ing_hello
:
case
send
_next_token
:
rc
=
produce_
hello
(
msg_
);
rc
=
produce_
next_token
(
msg_
);
if
(
rc
==
0
)
if
(
rc
==
0
)
state
=
waiting_for_welcome
;
state
=
recv_next_token
;
break
;
break
;
case
sending_initiate
:
case
almost_ready
:
rc
=
produce_initiate
(
msg_
);
state
=
ready
;
if
(
rc
==
0
)
state
=
waiting_for_token
;
break
;
case
sending_token
:
rc
=
produce_token
(
msg_
,
0
,
(
char
*
)
"o, hai!"
,
7
);
if
(
rc
==
0
)
state
=
waiting_for_ready
;
//state = expecting_another_token? waiting_for_token: waiting_for_ready;
break
;
break
;
default
:
default
:
errno
=
EAGAIN
;
errno
=
EAGAIN
;
rc
=
-
1
;
rc
=
-
1
;
break
;
}
}
return
rc
;
return
rc
;
}
}
...
@@ -72,135 +78,99 @@ int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_)
...
@@ -72,135 +78,99 @@ int zmq::gssapi_client_t::next_handshake_command (msg_t *msg_)
int
zmq
::
gssapi_client_t
::
process_handshake_command
(
msg_t
*
msg_
)
int
zmq
::
gssapi_client_t
::
process_handshake_command
(
msg_t
*
msg_
)
{
{
int
rc
=
0
;
int
rc
=
0
;
int
flags
=
0
;
gss_buffer_desc
buf
;
buf
.
value
=
NULL
;
buf
.
length
=
0
;
switch
(
state
)
{
switch
(
state
)
{
case
waiting_for_welcome
:
case
recv_next_token
:
rc
=
process_
welcome
(
msg_
);
rc
=
process_
next_token
(
msg_
);
if
(
rc
==
0
)
if
(
rc
==
0
)
state
=
se
nding_initiate
;
state
=
se
curity_context_established
?
almost_ready
:
send_next_token
;
break
;
break
;
case
waiting_for_token
:
case
almost_ready
:
rc
=
process_token
(
msg_
,
flags
,
&
buf
.
value
,
buf
.
length
);
state
=
ready
;
if
(
rc
==
0
)
state
=
sending_token
;
// state = expecting_another_token? sending_token: sending_ready;
break
;
case
waiting_for_ready
:
rc
=
process_ready
(
msg_
);
if
(
rc
==
0
)
state
=
ready
;
break
;
break
;
default
:
default
:
errno
=
EPROTO
;
errno
=
EPROTO
;
rc
=
-
1
;
rc
=
-
1
;
break
;
break
;
}
}
if
(
buf
.
value
)
{
free
(
buf
.
value
);
}
if
(
rc
==
0
)
{
if
(
rc
==
0
)
{
rc
=
msg_
->
close
();
rc
=
msg_
->
close
();
errno_assert
(
rc
==
0
);
errno_assert
(
rc
==
0
);
rc
=
msg_
->
init
();
rc
=
msg_
->
init
();
errno_assert
(
rc
==
0
);
errno_assert
(
rc
==
0
);
}
}
return
rc
;
return
rc
;
}
}
bool
zmq
::
gssapi_client_t
::
is_handshake_complete
()
const
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
==
ready
;
}
}
int
zmq
::
gssapi_client_t
::
produce_
hello
(
msg_t
*
msg_
)
const
int
zmq
::
gssapi_client_t
::
produce_
next_token
(
msg_t
*
msg_
)
{
{
const
std
::
string
username
=
"admin"
;
// First time through, import service_name into target_name
zmq_assert
(
username
.
length
()
<
256
);
if
(
target_name
==
GSS_C_NO_NAME
)
{
send_tok
.
value
=
service_name
;
const
std
::
string
password
=
"secret"
;
send_tok
.
length
=
strlen
(
service_name
);
zmq_assert
(
password
.
length
()
<
256
);
OM_uint32
maj
=
gss_import_name
(
&
min_stat
,
&
send_tok
,
gss_nt_service_name
,
&
target_name
);
const
size_t
command_size
=
6
+
1
+
username
.
length
()
+
1
+
password
.
length
();
if
(
maj
!=
GSS_S_COMPLETE
)
{
const
int
rc
=
msg_
->
init_size
(
command_size
);
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);
errno_assert
(
rc
==
0
);
return
-
1
;
}
unsigned
char
*
ptr
=
static_cast
<
unsigned
char
*>
(
msg_
->
data
());
}
memcpy
(
ptr
,
"
\x05
HELLO"
,
6
);
ptr
+=
6
;
*
ptr
++
=
static_cast
<
unsigned
char
>
(
username
.
length
());
memcpy
(
ptr
,
username
.
c_str
(),
username
.
length
());
ptr
+=
username
.
length
();
*
ptr
++
=
static_cast
<
unsigned
char
>
(
password
.
length
());
memcpy
(
ptr
,
password
.
c_str
(),
password
.
length
());
ptr
+=
password
.
length
();
return
0
;
maj_stat
=
gss_init_sec_context
(
&
init_sec_min_stat
,
cred
,
&
context
,
}
target_name
,
mechs
.
elements
,
gss_flags
,
0
,
NULL
,
token_ptr
,
NULL
,
&
send_tok
,
&
ret_flags
,
NULL
);
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
)
{
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);
int
zmq
::
gssapi_client_t
::
process_welcome
(
msg_t
*
msg_
)
gss_release_buffer
(
&
min_stat
,
&
send_tok
);
{
const
unsigned
char
*
ptr
=
static_cast
<
unsigned
char
*>
(
msg_
->
data
());
size_t
bytes_left
=
msg_
->
size
();
if
(
bytes_left
!=
8
||
memcmp
(
ptr
,
"
\x07
WELCOME"
,
8
))
{
if
(
maj_stat
!=
GSS_S_COMPLETE
&&
maj_stat
!=
GSS_S_CONTINUE_NEEDED
)
{
errno
=
EPROTO
;
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
);
return
-
1
;
return
-
1
;
}
}
return
0
;
return
0
;
}
}
int
zmq
::
gssapi_client_t
::
pro
duce_initiate
(
msg_t
*
msg_
)
const
int
zmq
::
gssapi_client_t
::
pro
cess_next_token
(
msg_t
*
msg_
)
{
{
unsigned
char
*
const
command_buffer
=
(
unsigned
char
*
)
malloc
(
512
);
if
(
maj_stat
==
GSS_S_CONTINUE_NEEDED
)
{
alloc_assert
(
command_buffer
);
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
)
{
unsigned
char
*
ptr
=
command_buffer
;
gss_release_name
(
&
min_stat
,
&
target_name
);
return
-
1
;
// Add mechanism string
}
memcpy
(
ptr
,
"
\x08
INITIATE"
,
9
);
token_ptr
=
&
recv_tok
;
ptr
+=
9
;
// Add socket type property
const
char
*
socket_type
=
socket_type_string
(
options
.
type
);
ptr
+=
add_property
(
ptr
,
"Socket-Type"
,
socket_type
,
strlen
(
socket_type
));
// Add identity property
if
(
options
.
type
==
ZMQ_REQ
||
options
.
type
==
ZMQ_DEALER
||
options
.
type
==
ZMQ_ROUTER
)
{
ptr
+=
add_property
(
ptr
,
"Identity"
,
options
.
identity
,
options
.
identity_size
);
}
}
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);
const
size_t
command_size
=
ptr
-
command_buffer
;
if
(
maj_stat
==
GSS_S_COMPLETE
)
const
int
rc
=
msg_
->
init_size
(
command_size
);
security_context_established
=
true
;
errno_assert
(
rc
==
0
);
memcpy
(
msg_
->
data
(),
command_buffer
,
command_size
);
free
(
command_buffer
);
return
0
;
return
0
;
}
}
int
zmq
::
gssapi_client_t
::
process_ready
(
msg_t
*
msg_
)
{
const
unsigned
char
*
ptr
=
static_cast
<
unsigned
char
*>
(
msg_
->
data
());
size_t
bytes_left
=
msg_
->
size
();
if
(
bytes_left
<
6
||
memcmp
(
ptr
,
"
\x05
READY"
,
6
))
{
errno
=
EPROTO
;
return
-
1
;
}
ptr
+=
6
;
bytes_left
-=
6
;
return
parse_metadata
(
ptr
,
bytes_left
);
}
src/gssapi_client.hpp
View file @
1445516c
...
@@ -46,22 +46,19 @@ namespace zmq
...
@@ -46,22 +46,19 @@ namespace zmq
private
:
private
:
enum
state_t
{
enum
state_t
{
sending_hello
,
send_next_token
,
waiting_for_welcome
,
recv_next_token
,
sending_initiate
,
almost_ready
,
sending_token
,
waiting_for_token
,
waiting_for_ready
,
ready
ready
};
};
state_t
state
;
state_t
state
;
gss_buffer_desc
*
token_ptr
;
gss_OID_set_desc
mechs
;
bool
security_context_established
;
int
produce_hello
(
msg_t
*
msg_
)
const
;
int
produce_next_token
(
msg_t
*
msg_
);
int
produce_initiate
(
msg_t
*
msg_
)
const
;
int
process_next_token
(
msg_t
*
msg_
);
int
process_welcome
(
msg_t
*
msg
);
int
process_ready
(
msg_t
*
msg_
);
};
};
}
}
...
...
src/gssapi_mechanism_base.cpp
View file @
1445516c
...
@@ -31,12 +31,29 @@
...
@@ -31,12 +31,29 @@
#include "gssapi_mechanism_base.hpp"
#include "gssapi_mechanism_base.hpp"
#include "wire.hpp"
#include "wire.hpp"
zmq
::
gssapi_mechanism_base_t
::
gssapi_mechanism_base_t
()
zmq
::
gssapi_mechanism_base_t
::
gssapi_mechanism_base_t
()
:
send_tok
(),
recv_tok
(),
in_buf
(),
target_name
(
GSS_C_NO_NAME
),
service_name
(
NULL
),
maj_stat
(
GSS_S_COMPLETE
),
min_stat
(
0
),
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
)
{
{
}
}
zmq
::
gssapi_mechanism_base_t
::~
gssapi_mechanism_base_t
()
zmq
::
gssapi_mechanism_base_t
::~
gssapi_mechanism_base_t
()
{
{
if
(
target_name
)
gss_release_name
(
&
min_stat
,
&
target_name
);
if
(
context
)
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
::
produce_token
(
msg_t
*
msg_
,
int
flags_
,
void
*
token_value_
,
size_t
token_length_
)
...
@@ -128,3 +145,31 @@ int zmq::gssapi_mechanism_base_t::process_token (msg_t *msg_, int &flags_, void
...
@@ -128,3 +145,31 @@ int zmq::gssapi_mechanism_base_t::process_token (msg_t *msg_, int &flags_, void
return
0
;
return
0
;
}
}
int
zmq
::
gssapi_mechanism_base_t
::
acquire_credentials
(
char
*
service_name_
,
gss_cred_id_t
*
cred_
)
{
OM_uint32
maj_stat
;
OM_uint32
min_stat
;
gss_name_t
server_name
;
gss_buffer_desc
name_buf
;
name_buf
.
value
=
service_name_
;
name_buf
.
length
=
strlen
((
char
*
)
name_buf
.
value
)
+
1
;
maj_stat
=
gss_import_name
(
&
min_stat
,
&
name_buf
,
gss_nt_service_name
,
&
server_name
);
if
(
maj_stat
!=
GSS_S_COMPLETE
)
return
-
1
;
maj_stat
=
gss_acquire_cred
(
&
min_stat
,
server_name
,
0
,
GSS_C_NO_OID_SET
,
GSS_C_ACCEPT
,
cred_
,
NULL
,
NULL
);
if
(
maj_stat
!=
GSS_S_COMPLETE
)
return
-
1
;
gss_release_name
(
&
min_stat
,
&
server_name
);
return
0
;
}
src/gssapi_mechanism_base.hpp
View file @
1445516c
...
@@ -41,6 +41,31 @@ namespace zmq
...
@@ -41,6 +41,31 @@ namespace zmq
protected
:
protected
:
int
produce_token
(
msg_t
*
msg_
,
int
flags_
,
void
*
token_value_
,
size_t
token_length_
);
int
produce_token
(
msg_t
*
msg_
,
int
flags_
,
void
*
token_value_
,
size_t
token_length_
);
int
process_token
(
msg_t
*
msg_
,
int
&
flags_
,
void
**
token_value_
,
size_t
&
token_length_
);
int
process_token
(
msg_t
*
msg_
,
int
&
flags_
,
void
**
token_value_
,
size_t
&
token_length_
);
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
);
gss_buffer_desc
send_tok
;
gss_buffer_desc
recv_tok
;
gss_buffer_desc
in_buf
;
gss_name_t
target_name
;
char
*
service_name
;
OM_uint32
maj_stat
;
OM_uint32
min_stat
;
OM_uint32
init_sec_min_stat
;
OM_uint32
ret_flags
;
OM_uint32
gss_flags
;
int
token_flags
;
gss_cred_id_t
cred
;
gss_ctx_id_t
context
;
};
};
}
}
...
...
src/gssapi_server.cpp
View file @
1445516c
...
@@ -38,13 +38,25 @@ zmq::gssapi_server_t::gssapi_server_t (session_base_t *session_,
...
@@ -38,13 +38,25 @@ zmq::gssapi_server_t::gssapi_server_t (session_base_t *session_,
mechanism_t
(
options_
),
mechanism_t
(
options_
),
session
(
session_
),
session
(
session_
),
peer_address
(
peer_address_
),
peer_address
(
peer_address_
),
expecting_zap_reply
(
false
),
state
(
recv_next_token
),
s
tate
(
waiting_for_hello
)
s
ecurity_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
maj_stat
=
GSS_S_CONTINUE_NEEDED
;
}
else
{
fprintf
(
stderr
,
"%s:%d: acquire creds failed
\n
"
,
__FILE__
,
__LINE__
);
/// FIXME remove
maj_stat
=
GSS_S_FAILURE
;
}
}
}
zmq
::
gssapi_server_t
::~
gssapi_server_t
()
zmq
::
gssapi_server_t
::~
gssapi_server_t
()
{
{
if
(
cred
)
gss_release_cred
(
&
min_stat
,
&
cred
);
}
}
int
zmq
::
gssapi_server_t
::
next_handshake_command
(
msg_t
*
msg_
)
int
zmq
::
gssapi_server_t
::
next_handshake_command
(
msg_t
*
msg_
)
...
@@ -52,24 +64,18 @@ int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_)
...
@@ -52,24 +64,18 @@ int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_)
int
rc
=
0
;
int
rc
=
0
;
switch
(
state
)
{
switch
(
state
)
{
case
send
ing_welcome
:
case
send
_next_token
:
rc
=
produce_
welcome
(
msg_
);
rc
=
produce_
next_token
(
msg_
);
if
(
rc
==
0
)
if
(
rc
==
0
)
state
=
waiting_for_initiate
;
state
=
security_context_established
?
almost_ready
:
recv_next_token
;
break
;
break
;
case
sending_token
:
case
almost_ready
:
rc
=
produce_token
(
msg_
,
0
,
(
char
*
)
"kthx! bye!"
,
10
);
state
=
ready
;
if
(
rc
==
0
)
state
=
waiting_for_token
;
//state = expecting_another_token? waiting_for_token: waiting_for_ready;
break
;
case
sending_ready
:
rc
=
produce_ready
(
msg_
);
if
(
rc
==
0
)
state
=
ready
;
break
;
break
;
default
:
default
:
errno
=
E
AGAIN
;
errno
=
E
PROTO
;
rc
=
-
1
;
rc
=
-
1
;
break
;
}
}
return
rc
;
return
rc
;
}
}
...
@@ -77,319 +83,94 @@ int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_)
...
@@ -77,319 +83,94 @@ int zmq::gssapi_server_t::next_handshake_command (msg_t *msg_)
int
zmq
::
gssapi_server_t
::
process_handshake_command
(
msg_t
*
msg_
)
int
zmq
::
gssapi_server_t
::
process_handshake_command
(
msg_t
*
msg_
)
{
{
int
rc
=
0
;
int
rc
=
0
;
int
flags
=
0
;
gss_buffer_desc
buf
;
buf
.
value
=
NULL
;
buf
.
length
=
0
;
switch
(
state
)
{
switch
(
state
)
{
case
waiting_for_hello
:
case
recv_next_token
:
rc
=
process_hello
(
msg_
);
rc
=
process_next_token
(
msg_
);
if
(
rc
==
0
)
state
=
expecting_zap_reply
?
waiting_for_zap_reply
:
sending_welcome
;
break
;
case
waiting_for_initiate
:
rc
=
process_initiate
(
msg_
);
if
(
rc
==
0
)
if
(
rc
==
0
)
state
=
send
ing
_token
;
state
=
send
_next
_token
;
break
;
break
;
case
waiting_for_token
:
case
almost_ready
:
rc
=
process_token
(
msg_
,
flags
,
&
buf
.
value
,
buf
.
length
);
state
=
ready
;
if
(
rc
==
0
)
state
=
sending_ready
;
// state = expecting_another_token? sending_token: sending_ready;
break
;
break
;
default
:
default
:
errno
=
E
PROTO
;
errno
=
E
AGAIN
;
rc
=
-
1
;
rc
=
-
1
;
break
;
break
;
}
}
if
(
buf
.
value
)
{
free
(
buf
.
value
);
}
if
(
rc
==
0
)
{
if
(
rc
==
0
)
{
rc
=
msg_
->
close
();
rc
=
msg_
->
close
();
errno_assert
(
rc
==
0
);
errno_assert
(
rc
==
0
);
rc
=
msg_
->
init
();
rc
=
msg_
->
init
();
errno_assert
(
rc
==
0
);
errno_assert
(
rc
==
0
);
}
}
return
rc
;
return
rc
;
}
}
bool
zmq
::
gssapi_server_t
::
is_handshake_complete
()
const
{
return
state
==
ready
;
}
int
zmq
::
gssapi_server_t
::
zap_msg_available
()
int
zmq
::
gssapi_server_t
::
zap_msg_available
()
{
{
if
(
state
!=
waiting_for_zap_reply
)
{
errno
=
EFSM
;
return
-
1
;
}
const
int
rc
=
receive_and_process_zap_reply
();
if
(
rc
==
0
)
state
=
sending_welcome
;
return
rc
;
}
int
zmq
::
gssapi_server_t
::
process_hello
(
msg_t
*
msg_
)
{
const
unsigned
char
*
ptr
=
static_cast
<
unsigned
char
*>
(
msg_
->
data
());
size_t
bytes_left
=
msg_
->
size
();
if
(
bytes_left
<
6
||
memcmp
(
ptr
,
"
\x05
HELLO"
,
6
))
{
errno
=
EPROTO
;
return
-
1
;
}
ptr
+=
6
;
bytes_left
-=
6
;
if
(
bytes_left
<
1
)
{
errno
=
EPROTO
;
return
-
1
;
}
const
size_t
username_length
=
static_cast
<
size_t
>
(
*
ptr
++
);
bytes_left
-=
1
;
if
(
bytes_left
<
username_length
)
{
errno
=
EPROTO
;
return
-
1
;
}
const
std
::
string
username
=
std
::
string
((
char
*
)
ptr
,
username_length
);
ptr
+=
username_length
;
bytes_left
-=
username_length
;
if
(
bytes_left
<
1
)
{
errno
=
EPROTO
;
return
-
1
;
}
const
size_t
password_length
=
static_cast
<
size_t
>
(
*
ptr
++
);
bytes_left
-=
1
;
if
(
bytes_left
<
password_length
)
{
errno
=
EPROTO
;
return
-
1
;
}
const
std
::
string
password
=
std
::
string
((
char
*
)
ptr
,
password_length
);
ptr
+=
password_length
;
bytes_left
-=
password_length
;
if
(
bytes_left
>
0
)
{
errno
=
EPROTO
;
return
-
1
;
}
// Use ZAP protocol (RFC 27) to authenticate the user.
int
rc
=
session
->
zap_connect
();
if
(
rc
==
0
)
{
send_zap_request
(
username
,
password
);
rc
=
receive_and_process_zap_reply
();
if
(
rc
!=
0
)
{
if
(
errno
!=
EAGAIN
)
return
-
1
;
expecting_zap_reply
=
true
;
}
}
return
0
;
return
0
;
}
}
int
zmq
::
gssapi_server_t
::
produce_welcome
(
msg_t
*
msg_
)
const
bool
zmq
::
gssapi_server_t
::
is_handshake_complete
(
)
const
{
{
const
int
rc
=
msg_
->
init_size
(
8
);
fprintf
(
stderr
,
"%s:%d: is_handshake_complete=%d
\n
"
,
__FILE__
,
__LINE__
,
(
state
==
ready
));
/// FIXME remove
errno_assert
(
rc
==
0
);
return
state
==
ready
;
memcpy
(
msg_
->
data
(),
"
\x07
WELCOME"
,
8
);
return
0
;
}
}
int
zmq
::
gssapi_server_t
::
pro
cess_initiate
(
msg_t
*
msg_
)
int
zmq
::
gssapi_server_t
::
pro
duce_next_token
(
msg_t
*
msg_
)
{
{
const
unsigned
char
*
ptr
=
static_cast
<
unsigned
char
*>
(
msg_
->
data
());
if
(
send_tok
.
length
!=
0
)
{
// client expects another token
size_t
bytes_left
=
msg_
->
size
();
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);
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
(
bytes_left
<
9
||
memcmp
(
ptr
,
"
\x08
INITIATE"
,
9
))
{
if
(
maj_stat
!=
GSS_S_COMPLETE
&&
maj_stat
!=
GSS_S_CONTINUE_NEEDED
)
{
errno
=
EPROTO
;
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
;
return
-
1
;
}
}
ptr
+=
9
;
bytes_left
-=
9
;
return
parse_metadata
(
ptr
,
bytes_left
);
}
int
zmq
::
gssapi_server_t
::
produce_ready
(
msg_t
*
msg_
)
const
{
unsigned
char
*
const
command_buffer
=
(
unsigned
char
*
)
malloc
(
512
);
alloc_assert
(
command_buffer
);
unsigned
char
*
ptr
=
command_buffer
;
// Add command name
memcpy
(
ptr
,
"
\x05
READY"
,
6
);
ptr
+=
6
;
// Add socket type property
const
char
*
socket_type
=
socket_type_string
(
options
.
type
);
ptr
+=
add_property
(
ptr
,
"Socket-Type"
,
socket_type
,
strlen
(
socket_type
));
// Add identity property
if
(
maj_stat
==
GSS_S_COMPLETE
)
{
if
(
options
.
type
==
ZMQ_REQ
gss_release_name
(
&
min_stat
,
&
target_name
);
||
options
.
type
==
ZMQ_DEALER
security_context_established
=
true
;
||
options
.
type
==
ZMQ_ROUTER
)
{
ptr
+=
add_property
(
ptr
,
"Identity"
,
options
.
identity
,
options
.
identity_size
);
}
}
const
size_t
command_size
=
ptr
-
command_buffer
;
const
int
rc
=
msg_
->
init_size
(
command_size
);
errno_assert
(
rc
==
0
);
memcpy
(
msg_
->
data
(),
command_buffer
,
command_size
);
free
(
command_buffer
);
return
0
;
return
0
;
}
}
void
zmq
::
gssapi_server_t
::
send_zap_request
(
const
std
::
string
&
username
,
int
zmq
::
gssapi_server_t
::
process_next_token
(
msg_t
*
msg_
)
const
std
::
string
&
password
)
{
int
rc
;
msg_t
msg
;
// Address delimiter frame
rc
=
msg
.
init
();
errno_assert
(
rc
==
0
);
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Version frame
rc
=
msg
.
init_size
(
3
);
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
"1.0"
,
3
);
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Request id frame
rc
=
msg
.
init_size
(
1
);
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
"1"
,
1
);
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Domain frame
rc
=
msg
.
init_size
(
options
.
zap_domain
.
length
());
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
options
.
zap_domain
.
c_str
(),
options
.
zap_domain
.
length
());
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Address frame
rc
=
msg
.
init_size
(
peer_address
.
length
());
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
peer_address
.
c_str
(),
peer_address
.
length
());
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Identity frame
rc
=
msg
.
init_size
(
options
.
identity_size
);
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
options
.
identity
,
options
.
identity_size
);
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Mechanism frame
rc
=
msg
.
init_size
(
6
);
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
"GSSAPI"
,
6
);
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Username frame
rc
=
msg
.
init_size
(
username
.
length
());
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
username
.
c_str
(),
username
.
length
());
msg
.
set_flags
(
msg_t
::
more
);
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
// Password frame
rc
=
msg
.
init_size
(
password
.
length
());
errno_assert
(
rc
==
0
);
memcpy
(
msg
.
data
(),
password
.
c_str
(),
password
.
length
());
rc
=
session
->
write_zap_msg
(
&
msg
);
errno_assert
(
rc
==
0
);
}
int
zmq
::
gssapi_server_t
::
receive_and_process_zap_reply
()
{
{
int
rc
=
0
;
if
(
maj_stat
==
GSS_S_CONTINUE_NEEDED
)
{
msg_t
msg
[
7
];
// ZAP reply consists of 7 frames
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
)
{
// Initialize all reply frames
if
(
target_name
!=
GSS_C_NO_NAME
)
for
(
int
i
=
0
;
i
<
7
;
i
++
)
{
gss_release_name
(
&
min_stat
,
&
target_name
);
rc
=
msg
[
i
].
init
();
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);
errno_assert
(
rc
==
0
);
return
-
1
;
}
for
(
int
i
=
0
;
i
<
7
;
i
++
)
{
rc
=
session
->
read_zap_msg
(
&
msg
[
i
]);
if
(
rc
==
-
1
)
break
;
if
((
msg
[
i
].
flags
()
&
msg_t
::
more
)
==
(
i
<
6
?
0
:
msg_t
::
more
))
{
errno
=
EPROTO
;
rc
=
-
1
;
break
;
}
}
}
}
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);
maj_stat
=
gss_accept_sec_context
(
&
init_sec_min_stat
,
&
context
,
cred
,
&
recv_tok
,
GSS_C_NO_CHANNEL_BINDINGS
,
&
target_name
,
&
doid
,
&
send_tok
,
&
ret_flags
,
NULL
,
NULL
);
if
(
rc
!=
0
)
if
(
recv_tok
.
value
)
{
goto
error
;
free
(
recv_tok
.
value
);
recv_tok
.
value
=
NULL
;
// Address delimiter frame
if
(
msg
[
0
].
size
()
>
0
)
{
rc
=
-
1
;
errno
=
EPROTO
;
goto
error
;
}
// Version frame
if
(
msg
[
1
].
size
()
!=
3
||
memcmp
(
msg
[
1
].
data
(),
"1.0"
,
3
))
{
rc
=
-
1
;
errno
=
EPROTO
;
goto
error
;
}
// Request id frame
if
(
msg
[
2
].
size
()
!=
1
||
memcmp
(
msg
[
2
].
data
(),
"1"
,
1
))
{
rc
=
-
1
;
errno
=
EPROTO
;
goto
error
;
}
// Status code frame
if
(
msg
[
3
].
size
()
!=
3
||
memcmp
(
msg
[
3
].
data
(),
"200"
,
3
))
{
rc
=
-
1
;
errno
=
EACCES
;
goto
error
;
}
// Process metadata frame
rc
=
parse_metadata
(
static_cast
<
const
unsigned
char
*>
(
msg
[
6
].
data
()),
msg
[
6
].
size
());
error
:
for
(
int
i
=
0
;
i
<
7
;
i
++
)
{
const
int
rc2
=
msg
[
i
].
close
();
errno_assert
(
rc2
==
0
);
}
}
return
rc
;
return
0
;
}
}
src/gssapi_server.hpp
View file @
1445516c
...
@@ -50,34 +50,21 @@ namespace zmq
...
@@ -50,34 +50,21 @@ namespace zmq
private
:
private
:
enum
state_t
{
enum
state_t
{
waiting_for_hello
,
send_next_token
,
sending_welcome
,
recv_next_token
,
waiting_for_initiate
,
sending_token
,
waiting_for_token
,
sending_ready
,
waiting_for_zap_reply
,
waiting_for_zap_reply
,
almost_ready
,
ready
ready
};
};
session_base_t
*
const
session
;
session_base_t
*
const
session
;
const
std
::
string
peer_address
;
const
std
::
string
peer_address
;
// True iff we are awaiting reply from ZAP reply.
bool
expecting_zap_reply
;
state_t
state
;
state_t
state
;
bool
security_context_established
;
gss_OID
doid
;
int
produce_welcome
(
msg_t
*
msg_
)
const
;
int
produce_next_token
(
msg_t
*
msg_
);
int
produce_ready
(
msg_t
*
msg_
)
const
;
int
process_next_token
(
msg_t
*
msg_
);
int
process_hello
(
msg_t
*
msg_
);
int
process_initiate
(
msg_t
*
msg_
);
void
send_zap_request
(
const
std
::
string
&
username
,
const
std
::
string
&
password
);
int
receive_and_process_zap_reply
();
};
};
}
}
...
...
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