在C/C++中获取Kerberos票证



有人知道如何使用C/C++中的MIT krb5 API从密钥分发中心(KDC(获取票证吗

我已经有了一个工作的Java客户端,它使用GSS-API从KDC(使用本地TGT(获取票证,并将其转发到Java服务器。

服务器使用以下逻辑接受安全上下文:

private GSSContext acceptSecurityContext(Subject serverSubject, final byte[] kerberosServiceTicket) {
return Subject.doAs(serverSubject, (PrivilegedAction<GSSContext>) () -> {
GSSContext gssContext;
try {
gssContext = manager.createContext((GSSCredential) null);
} catch (GSSException ex) {
LOGGER.warn("Could not create Kerberos gssContext: " + ex.getMessage(), ex);
return null;
}
try {
gssContext.acceptSecContext(kerberosServiceTicket, 0, kerberosServiceTicket.length);
} catch (GSSException ex) {
LOGGER.warn("Could not accept security context: " + ex.getMessage(), ex);
return null;
}
return gssContext;
});
}

我正在尝试使用MIT krb5 API实现一个类似于Java的C客户端,但我似乎无法使其工作。到目前为止,这是我的C客户端代码:

krb5_context context;
krb5_ccache ccache;
krb5_creds *outCreds = NULL;
krb5_creds inCreds;
int retval;
char *principal = "...";
retval = krb5_init_secure_context(&context);
...
retval = krb5_cc_default(context, &ccache);
...
memset(&inCreds, 0, sizeof(inCreds));
retval = krb5_parse_name(context, principal, &inCreds.server);
...
retval = krb5_cc_get_principal(context, ccache, &inCreds.client);
...
retval = krb5_get_credentials(context, 0, ccache, &inCreds, &outCreds);
...
// also tried using the following: krb5Ticket->enc_part.ciphertext.data
// (maybe this is the correct way, but I should somehow decrypt it and use krb5Ticket->enc_part2 ?)
// retval = krb5_decode_ticket(&outCreds->ticket, &krb5Ticket);
// ...
char *base64KerberosTicket = base64_encode(outCreds->ticket.data, strlen(outCreds->ticket.data));
char *response = loginKerberos(base64KerberosTicket);
...

经过进一步的阅读,我的方法似乎不适合我的用例。我本应该直接使用GSS-API的。

以下片段有效:

gss_name_t get_spn(char *spn)
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER;
gss_name_t spn_gss_name = GSS_C_NO_NAME;
name_buf.value = spn;
name_buf.length = strlen(name_buf.value);
maj_stat = gss_import_name(&min_stat, &name_buf, GSS_KRB5_NT_PRINCIPAL_NAME, &spn_gss_name);
if (GSS_ERROR(maj_stat))
{
display_status("Major status", maj_stat, GSS_C_GSS_CODE);
display_status("Minor status", min_stat, GSS_C_MECH_CODE);
}
return spn_gss_name;
}
char* init_sec_context(char *spn)
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
OM_uint32 flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
gss_name_t spn_gss_name = get_spn(spn);
gss_buffer_desc output_token;
char *base64_encoded_kerberos_token = NULL;
maj_stat = gss_init_sec_context( //
&min_stat, // minor_status
GSS_C_NO_CREDENTIAL, // claimant_cred_handle
&gss_context, // context_handle
spn_gss_name, // target_name
GSS_C_NO_OID, // mech_type of the desired mechanism
flags, // req_flags
0, // time_req for the context to remain valid. 0 for default lifetime.
GSS_C_NO_CHANNEL_BINDINGS, // channel bindings
GSS_C_NO_BUFFER, // input token 
NULL, // actual_mech_type
&output_token, // output token 
NULL, // ret_flags
NULL // time_req
);
if (GSS_ERROR(maj_stat))
{
...
}
else if (output_token.length != 0)
{
base64_encoded_kerberos_token = base64_encode(output_token.value, output_token.length, &(output_token.length));
}
if (gss_context != GSS_C_NO_CONTEXT)
{
gss_delete_sec_context(&min_stat, &gss_context, GSS_C_NO_BUFFER);
}
if (spn_gss_name != GSS_C_NO_NAME)
{
gss_release_name(&min_stat, &spn_gss_name);
}
gss_release_buffer(&min_stat, &output_token);
return base64_encoded_kerberos_token;
}

最新更新