/*
Copyright (C) 2013 Simo Sorce <simo@samba.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GSS_NTLMSSP_H_
#define _GSS_NTLMSSP_H_
#include "ntlm.h"
#include "crypto.h"
#include "gssapi_ntlmssp.h"
#include "debug.h"
#define DEF_NB_DOMAIN "WORKSTATION"
#define MAX_CHALRESP_LIFETIME 36 * 60 * 60 /* 36 hours in seconds */
#define SEC_LEVEL_MIN 0
#define SEC_LEVEL_MAX 5
#define SEC_LM_OK 0x01
#define SEC_NTLM_OK 0x02
#define SEC_EXT_SEC_OK 0x04
#define SEC_V2_ONLY 0x08
#define SEC_DC_LM_OK 0x10
#define SEC_DC_NTLM_OK 0x20
#define SEC_DC_V2_OK 0x40
#define NTLMSSP_DEFAULT_CLIENT_FLAGS ( \
NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \
NTLMSSP_NEGOTIATE_128 | \
NTLMSSP_NEGOTIATE_56 | \
NTLMSSP_NEGOTIATE_NTLM | \
NTLMSSP_REQUEST_TARGET | \
NTLMSSP_NEGOTIATE_OEM | \
NTLMSSP_NEGOTIATE_UNICODE)
#define NTLMSSP_DEFAULT_SERVER_FLAGS ( \
NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \
NTLMSSP_NEGOTIATE_56 | \
NTLMSSP_NEGOTIATE_KEY_EXCH | \
NTLMSSP_NEGOTIATE_128 | \
NTLMSSP_NEGOTIATE_VERSION | \
NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \
NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED | \
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED | \
NTLMSSP_NEGOTIATE_NTLM | \
NTLMSSP_NEGOTIATE_SEAL | \
NTLMSSP_NEGOTIATE_SIGN | \
NTLMSSP_REQUEST_TARGET | \
NTLMSSP_NEGOTIATE_OEM | \
NTLMSSP_NEGOTIATE_UNICODE)
#define NTLMSSP_CTX_FLAG_ESTABLISHED 0x01 /* context was established */
#define NTLMSSP_CTX_FLAG_SPNEGO_CAN_MIC 0x02 /* SPNEGO asks for MIC */
#define NTLMSSP_CTX_FLAG_AUTH_WITH_MIC 0x04 /* Auth MIC was created */
struct gssntlm_name {
enum ntlm_name_type {
GSSNTLM_NAME_NULL,
GSSNTLM_NAME_ANON,
GSSNTLM_NAME_USER,
GSSNTLM_NAME_SERVER
} type;
union {
struct {
char *domain;
char *name;
} user;
struct {
char *name;
} server;
} data;
};
struct gssntlm_cred {
enum ntlm_cred_type {
GSSNTLM_CRED_NONE,
GSSNTLM_CRED_ANON,
GSSNTLM_CRED_USER,
GSSNTLM_CRED_SERVER,
GSSNTLM_CRED_EXTERNAL,
} type;
union {
struct {
int dummy;
} anon;
struct {
struct gssntlm_name user;
struct ntlm_key nt_hash;
struct ntlm_key lm_hash;
} user;
struct {
struct gssntlm_name name;
} server;
struct {
struct gssntlm_name user;
} external;
} cred;
};
struct gssntlm_ctx {
enum gssntlm_role {
GSSNTLM_CLIENT,
GSSNTLM_SERVER,
GSSNTLM_DOMAIN_SERVER,
GSSNTLM_DOMAIN_CONTROLLER
} role;
enum {
NTLMSSP_STAGE_INIT = 0,
NTLMSSP_STAGE_NEGOTIATE,
NTLMSSP_STAGE_CHALLENGE,
NTLMSSP_STAGE_AUTHENTICATE,
NTLMSSP_STAGE_DONE
} stage;
uint8_t sec_req;
char *workstation;
struct ntlm_ctx *ntlm;
struct ntlm_buffer nego_msg;
struct ntlm_buffer chal_msg;
struct ntlm_buffer auth_msg;
struct gssntlm_name source_name;
struct gssntlm_name target_name;
uint8_t server_chal[8];
/* requested gss fags */
uint32_t gss_flags;
/* negotiated flags */
uint32_t neg_flags;
/* TODO: Add whitelist of servers we are allowed to communicate with */
struct ntlm_key exported_session_key;
struct ntlm_signseal_state crypto_state;
uint32_t int_flags;
time_t expiration_time;
};
#define set_GSSERRS(min, maj) \
(void)DEBUG_GSS_ERRORS((retmaj = (maj)), (retmin = (min)))
#define set_GSSERR(min) set_GSSERRS((min), GSS_S_FAILURE)
static inline uint32_t gssntlmssp_ret_err(uint32_t *s, uint32_t n, uint32_t j)
{
if (!s) return GSS_S_CALL_INACCESSIBLE_WRITE;
*s = n;
return j;
}
#define GSSERR() gssntlmssp_ret_err(minor_status, retmin, retmaj)
#define GSSERRS(min, maj) \
DEBUG_GSS_ERRORS((retmaj = (maj)), (retmin = (min))) ? 0 : \
gssntlmssp_ret_err(minor_status, retmin, retmaj)
uint8_t gssntlm_required_security(int security_level, struct gssntlm_ctx *ctx);
void gssntlm_set_role(struct gssntlm_ctx *ctx,
int desired, char *nb_domain_name);
bool gssntlm_role_is_client(struct gssntlm_ctx *ctx);
bool gssntlm_role_is_server(struct gssntlm_ctx *ctx);
bool gssntlm_role_is_domain_member(struct gssntlm_ctx *ctx);
bool gssntlm_sec_lm_ok(struct gssntlm_ctx *ctx);
bool gssntlm_sec_ntlm_ok(struct gssntlm_ctx *ctx);
bool gssntlm_ext_sec_ok(struct gssntlm_ctx *ctx);
uint32_t gssntlm_context_is_valid(struct gssntlm_ctx *ctx,
time_t *time_now);
int gssntlm_get_lm_compatibility_level(void);
void gssntlm_int_release_name(struct gssntlm_name *name);
void gssntlm_int_release_cred(struct gssntlm_cred *cred);
int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst);
int gssntlm_copy_creds(struct gssntlm_cred *in, struct gssntlm_cred *out);
uint32_t external_netbios_get_names(char **computer, char **domain);
uint32_t external_get_creds(struct gssntlm_name *name,
struct gssntlm_cred *cred);
uint32_t external_cli_auth(struct gssntlm_ctx *ctx,
struct gssntlm_cred *cred,
uint32_t in_flags,
gss_channel_bindings_t input_chan_bindings);
uint32_t external_srv_auth(struct gssntlm_ctx *ctx,
struct gssntlm_cred *cred,
struct ntlm_buffer *nt_chal_resp,
struct ntlm_buffer *lm_chal_resp,
struct ntlm_key *session_base_key);
uint32_t netbios_get_names(char *computer_name,
char **netbios_host, char **netbios_domain);
bool is_ntlm_v1(struct ntlm_buffer *nt_chal_resp);
uint32_t gssntlm_cli_auth(uint32_t *minor,
struct gssntlm_ctx *ctx,
struct gssntlm_cred *cred,
struct ntlm_buffer *target_info,
uint32_t in_flags,
gss_channel_bindings_t input_chan_bindings);
uint32_t gssntlm_srv_auth(uint32_t *minor,
struct gssntlm_ctx *ctx,
struct gssntlm_cred *cred,
struct ntlm_buffer *nt_chal_resp,
struct ntlm_buffer *lm_chal_resp,
struct ntlm_key *key_exchange_key);
extern const gss_OID_desc gssntlm_oid;
uint32_t gssntlm_acquire_cred(uint32_t *minor_status,
gss_name_t desired_name,
uint32_t time_req,
gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
uint32_t *time_rec);
uint32_t gssntlm_acquire_cred_from(uint32_t *minor_status,
gss_name_t desired_name,
uint32_t time_req,
gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_const_key_value_set_t cred_store,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
uint32_t *time_rec);
uint32_t gssntlm_acquire_cred_with_password(uint32_t *minor_status,
gss_name_t desired_name,
gss_buffer_t password,
uint32_t time_req,
gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
gss_cred_id_t *output_cred_handle,
gss_OID_set *actual_mechs,
uint32_t *time_rec);
uint32_t gssntlm_release_cred(uint32_t *minor_status,
gss_cred_id_t *cred_handle);
uint32_t gssntlm_import_name(uint32_t *minor_status,
gss_buffer_t input_name_buffer,
gss_OID input_name_type,
gss_name_t *output_name);
uint32_t gssntlm_import_name_by_mech(uint32_t *minor_status,
gss_const_OID mech_type,
gss_buffer_t input_name_buffer,
gss_OID input_name_type,
gss_name_t *output_name);
uint32_t gssntlm_duplicate_name(uint32_t *minor_status,
const gss_name_t input_name,
gss_name_t *dest_name);
uint32_t gssntlm_release_name(uint32_t *minor_status,
gss_name_t *input_name);
uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
gss_cred_id_t claimant_cred_handle,
gss_ctx_id_t *context_handle,
gss_name_t target_name,
gss_OID mech_type,
uint32_t req_flags,
uint32_t time_req,
gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token,
gss_OID *actual_mech_type,
gss_buffer_t output_token,
uint32_t *ret_flags,
uint32_t *time_rec);
uint32_t gssntlm_delete_sec_context(uint32_t *minor_status,
gss_ctx_id_t *context_handle,
gss_buffer_t output_token);
uint32_t gssntlm_context_time(uint32_t *minor_status,
gss_ctx_id_t context_handle,
uint32_t *time_rec);
uint32_t gssntlm_accept_sec_context(uint32_t *minor_status,
gss_ctx_id_t *context_handle,
gss_cred_id_t acceptor_cred_handle,
gss_buffer_t input_token_buffer,
gss_channel_bindings_t input_chan_bindings,
gss_name_t *src_name,
gss_OID *mech_type,
gss_buffer_t output_token,
uint32_t *ret_flags,
uint32_t *time_rec,
gss_cred_id_t *delegated_cred_handle);
uint32_t gssntlm_set_sec_context_option(uint32_t *minor_status,
gss_ctx_id_t *context_handle,
const gss_OID desired_object,
const gss_buffer_t value);
uint32_t gssntlm_inquire_sec_context_by_oid(uint32_t *minor_status,
const gss_ctx_id_t context_handle,
const gss_OID desired_object,
gss_buffer_set_t *data_set);
uint32_t gssntlm_get_mic(uint32_t *minor_status,
gss_ctx_id_t context_handle,
gss_qop_t qop_req,
gss_buffer_t message_buffer,
gss_buffer_t message_token);
uint32_t gssntlm_verify_mic(uint32_t *minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t message_buffer,
gss_buffer_t message_token,
gss_qop_t *qop_state);
uint32_t gssntlm_wrap(uint32_t *minor_status,
gss_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
gss_buffer_t input_message_buffer,
int *conf_state,
gss_buffer_t output_message_buffer);
uint32_t gssntlm_unwrap(uint32_t *minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t input_message_buffer,
gss_buffer_t output_message_buffer,
int *conf_state,
gss_qop_t *qop_state);
uint32_t gssntlm_wrap_size_limit(uint32_t *minor_status,
gss_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
uint32_t req_output_size,
uint32_t *max_input_size);
uint32_t gssntlm_inquire_context(uint32_t *minor_status,
gss_ctx_id_t context_handle,
gss_name_t *src_name,
gss_name_t *targ_name,
uint32_t *lifetime_rec,
gss_OID *mech_type,
uint32_t *ctx_flags,
int *locally_initiated,
int *open);
uint32_t gssntlm_display_name(uint32_t *minor_status,
gss_name_t input_name,
gss_buffer_t output_name_buffer,
gss_OID *output_name_type);
uint32_t gssntlm_localname(uint32_t *minor_status,
const gss_name_t name,
gss_const_OID mech_type,
gss_buffer_t localname);
uint32_t gssntlm_inquire_cred(uint32_t *minor_status,
gss_cred_id_t cred_handle,
gss_name_t *name,
uint32_t *lifetime,
gss_cred_usage_t *cred_usage,
gss_OID_set *mechanisms);
uint32_t gssntlm_inquire_cred_by_mech(uint32_t *minor_status,
gss_cred_id_t cred_handle,
gss_OID mech_type,
gss_name_t *name,
uint32_t *initiator_lifetime,
uint32_t *acceptor_lifetime,
gss_cred_usage_t *cred_usage);
uint32_t gssntlm_export_sec_context(uint32_t *minor_status,
gss_ctx_id_t *context_handle,
gss_buffer_t interprocess_token);
uint32_t gssntlm_import_sec_context(uint32_t *minor_status,
gss_buffer_t interprocess_token,
gss_ctx_id_t *context_handle);
uint32_t gssntlm_export_cred(uint32_t *minor_status,
gss_cred_id_t cred_handle,
gss_buffer_t token);
uint32_t gssntlm_import_cred(uint32_t *minor_status,
gss_buffer_t token,
gss_cred_id_t *cred_handle);
uint32_t gssntlm_display_status(uint32_t *minor_status,
uint32_t status_value,
int status_type,
gss_OID mech_type,
uint32_t *message_context,
gss_buffer_t status_string);
uint32_t gssntlm_inquire_name(uint32_t *minor_status,
gss_name_t name,
int *name_is_MN,
gss_OID *MN_mech,
gss_buffer_set_t *attrs);
#endif /* _GSS_NTLMSSP_H_ */