* Copyright (c) 2003 The Reed Institute
* Copyright (c) 2004 Bjoern Fernhomberg
* All Rights Reserved. See COPYRIGHT.
* Copyright (c) 2003 The Reed Institute
* Copyright (c) 2004 Bjoern Fernhomberg
* All Rights Reserved. See COPYRIGHT.
-static void log_status( char *s, OM_uint32 major_status,
- OM_uint32 minor_status )
+static void log_status( char *s, OM_uint32 major_status,
+ OM_uint32 minor_status )
{
gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
OM_uint32 min_status, maj_status;
OM_uint32 maj_ctx = 0, min_ctx = 0;
while (1) {
{
gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
OM_uint32 min_status, maj_status;
OM_uint32 maj_ctx = 0, min_ctx = 0;
while (1) {
- maj_status = gss_display_status( &min_status, major_status,
- GSS_C_GSS_CODE, GSS_C_NULL_OID,
- &maj_ctx, &msg );
+ maj_status = gss_display_status( &min_status, major_status,
+ GSS_C_GSS_CODE, GSS_C_NULL_OID,
+ &maj_ctx, &msg );
LOG(log_info, logtype_uams, "uams_gss.c :do_gss_auth: %s %.*s (error %s)", s,
LOG(log_info, logtype_uams, "uams_gss.c :do_gss_auth: %s %.*s (error %s)", s,
- (int)msg.length, msg.value, strerror(errno));
- gss_release_buffer(&min_status, &msg);
+ (int)msg.length, msg.value, strerror(errno));
+ gss_release_buffer(&min_status, &msg);
- maj_status = gss_display_status( &min_status, minor_status,
- GSS_C_MECH_CODE, GSS_C_NULL_OID, // gss_mech_krb5,
- &min_ctx, &msg );
- LOG(log_info, logtype_uams, "uams_gss.c :do_gss_auth: %s %.*s (error %s)", s,
- (int)msg.length, msg.value, strerror(errno));
- gss_release_buffer(&min_status, &msg);
-
- if (!min_ctx)
- break;
+ maj_status = gss_display_status( &min_status, minor_status,
+ GSS_C_MECH_CODE, GSS_C_NULL_OID, // gss_mech_krb5,
+ &min_ctx, &msg );
+ LOG(log_info, logtype_uams, "uams_gss.c :do_gss_auth: %s %.*s (error %s)", s,
+ (int)msg.length, msg.value, strerror(errno));
+ gss_release_buffer(&min_status, &msg);
+
+ if (!min_ctx)
+ break;
- if (uam_afpserver_option(obj, UAM_OPTION_KRB5REALM, (void*) &realm, &realmlen) < 0)
- return 1;
- if (uam_afpserver_option(obj, UAM_OPTION_FQDN, (void*) &fqdn, &fqdnlen) < 0)
- return 1;
+ if (uam_afpserver_option(obj, UAM_OPTION_KRB5REALM, (void*) &realm, &realmlen) < 0)
+ return 1;
+ if (uam_afpserver_option(obj, UAM_OPTION_FQDN, (void*) &fqdn, &fqdnlen) < 0)
+ return 1;
if (uam_afpserver_option(obj, UAM_OPTION_KRB5SERVICE, (void *)&service, &servicelen) < 0)
return 1;
/* we need all the info, log error and return if one's missing */
if (!service || !servicelen || !fqdn || !fqdnlen || !realm || !realmlen) {
if (uam_afpserver_option(obj, UAM_OPTION_KRB5SERVICE, (void *)&service, &servicelen) < 0)
return 1;
/* we need all the info, log error and return if one's missing */
if (!service || !servicelen || !fqdn || !fqdnlen || !realm || !realmlen) {
principal_length = servicelen + 1 + fqdnlen + 1 + realmlen + 1;
if ( NULL == (principal = (char*) malloc( principal_length)) ) {
LOG(log_error, logtype_uams,
principal_length = servicelen + 1 + fqdnlen + 1 + realmlen + 1;
if ( NULL == (principal = (char*) malloc( principal_length)) ) {
LOG(log_error, logtype_uams,
strlcpy( principal, service, principal_length);
strlcat( principal, "/", principal_length);
strlcpy( principal, service, principal_length);
strlcat( principal, "/", principal_length);
strlcat( principal, "@", principal_length);
strlcat( principal, realm, principal_length);
strlcat( principal, "@", principal_length);
strlcat( principal, realm, principal_length);
LOG(log_debug, logtype_uams, "get_afpd_principal: importing principal `%s'", principal);
major_status = gss_import_name( &minor_status,
LOG(log_debug, logtype_uams, "get_afpd_principal: importing principal `%s'", principal);
major_status = gss_import_name( &minor_status,
* Get rid of malloc'ed memmory.
* Don't release the s_princ_buffer, we free principal instead.
*/
* Get rid of malloc'ed memmory.
* Don't release the s_princ_buffer, we free principal instead.
*/
* To extract the unix username, use gss_display_name on client_name.
* We do rely on gss_display_name returning a zero terminated string.
* The username returned contains the realm and possibly an instance.
* To extract the unix username, use gss_display_name on client_name.
* We do rely on gss_display_name returning a zero terminated string.
* The username returned contains the realm and possibly an instance.
* gss_wrap afpd's session_key.
* This is needed fo OS X 10.3 clients. They request this information
* with type 8 (kGetKerberosSessionKey) on FPGetSession.
* gss_wrap afpd's session_key.
* This is needed fo OS X 10.3 clients. They request this information
* with type 8 (kGetKerberosSessionKey) on FPGetSession.
Require both confidentiality and integrity services */
gss_wrap (&status, context, 1, GSS_C_QOP_DEFAULT, &sesskey_buff, NULL, &wrap_buff);
if ( status != GSS_S_COMPLETE) {
LOG(log_error, logtype_uams, "wrap_sessionkey: failed to gss_wrap sessionkey");
Require both confidentiality and integrity services */
gss_wrap (&status, context, 1, GSS_C_QOP_DEFAULT, &sesskey_buff, NULL, &wrap_buff);
if ( status != GSS_S_COMPLETE) {
LOG(log_error, logtype_uams, "wrap_sessionkey: failed to gss_wrap sessionkey");
return 1;
}
/* store the wrapped session key in afpd's session_info struct */
if ( NULL == (sinfo->cryptedkey = malloc ( wrap_buff.length )) ) {
return 1;
}
/* store the wrapped session key in afpd's session_info struct */
if ( NULL == (sinfo->cryptedkey = malloc ( wrap_buff.length )) ) {
- LOG(log_error, logtype_uams,
- "wrap_sessionkey: out of memory tyring to allocate %u bytes",
+ LOG(log_error, logtype_uams,
+ "wrap_sessionkey: out of memory tyring to allocate %u bytes",
LOG(log_debug, logtype_uams,
"acquire credentials: acquiring credentials (uid = %d, keytab = %s)",
(int)geteuid(), getenv( "KRB5_KTNAME") );
LOG(log_debug, logtype_uams,
"acquire credentials: acquiring credentials (uid = %d, keytab = %s)",
(int)geteuid(), getenv( "KRB5_KTNAME") );
- /*
- * Acquire credentials usable for accepting context negotiations.
- * Credentials are for server_name, have an indefinite lifetime,
- * have no specific mechanisms, are to be used for accepting context
- * negotiations and are to be placed in server_creds.
- * We don't care about the mechanisms or about the time for which they are valid.
- */
+ /*
+ * Acquire credentials usable for accepting context negotiations.
+ * Credentials are for server_name, have an indefinite lifetime,
+ * have no specific mechanisms, are to be used for accepting context
+ * negotiations and are to be placed in server_creds.
+ * We don't care about the mechanisms or about the time for which they are valid.
+ */
- GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT,
- server_creds, NULL, NULL );
+ GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT,
+ server_creds, NULL, NULL );
if (major_status != GSS_S_COMPLETE) {
log_status( "acquire_cred", major_status, minor_status );
return 1;
}
if (major_status != GSS_S_COMPLETE) {
log_status( "acquire_cred", major_status, minor_status );
return 1;
}
-static int accept_sec_context (gss_ctx_id_t *context, gss_cred_id_t server_creds,
- gss_buffer_desc *ticket_buffer, gss_name_t *client_name,
- gss_buffer_desc *authenticator_buff)
+static int accept_sec_context (gss_ctx_id_t *context, gss_cred_id_t server_creds,
+ gss_buffer_desc *ticket_buffer, gss_name_t *client_name,
+ gss_buffer_desc *authenticator_buff)
- LOG(log_debug, logtype_uams, "accept_context: accepting context (ticketlen: %u)",
+ LOG(log_debug, logtype_uams, "accept_context: accepting context (ticketlen: %u)",
* We don't act as a proxy either.
*/
major_status = gss_accept_sec_context( &minor_status, context,
* We don't act as a proxy either.
*/
major_status = gss_accept_sec_context( &minor_status, context,
- server_creds, ticket_buffer, GSS_C_NO_CHANNEL_BINDINGS,
- client_name, NULL, authenticator_buff,
- &ret_flags, NULL, NULL );
+ server_creds, ticket_buffer, GSS_C_NO_CHANNEL_BINDINGS,
+ client_name, NULL, authenticator_buff,
+ &ret_flags, NULL, NULL );
if (major_status != GSS_S_COMPLETE) {
log_status( "accept_sec_context", major_status, minor_status );
if (major_status != GSS_S_COMPLETE) {
log_status( "accept_sec_context", major_status, minor_status );
/* return 0 on success */
static int do_gss_auth(void *obj, char *ibuf, int ticket_len,
/* return 0 on success */
static int do_gss_auth(void *obj, char *ibuf, int ticket_len,
- char *rbuf, int *rbuflen, char *username, int ulen,
- struct session_info *sinfo )
+ char *rbuf, int *rbuflen, char *username, int ulen,
+ struct session_info *sinfo )
/* Now we have to acquire our credentials */
if ((ret = acquire_credentials (&server_name, &server_creds)))
/* Now we have to acquire our credentials */
if ((ret = acquire_credentials (&server_name, &server_creds)))
- /*
- * Try to accept the secondary context, using the ticket/token the
- * client sent us. Ticket is stored at current ibuf position.
- * Don't try to release ticket_buffer later, it points into ibuf!
+ /*
+ * Try to accept the secondary context, using the ticket/token the
+ * client sent us. Ticket is stored at current ibuf position.
+ * Don't try to release ticket_buffer later, it points into ibuf!
- ret = accept_sec_context (&context_handle, server_creds, &ticket_buffer,
- &client_name, &authenticator_buff);
+ ret = accept_sec_context (&context_handle, server_creds, &ticket_buffer,
+ &client_name, &authenticator_buff);
username for afpd and gss_wrap the sessionkey */
if ( 0 == (ret = get_client_username(username, ulen, &client_name)) ) {
ret = wrap_sessionkey(context_handle, sinfo);
}
if (!ret) {
username for afpd and gss_wrap the sessionkey */
if ( 0 == (ret = get_client_username(username, ulen, &client_name)) ) {
ret = wrap_sessionkey(context_handle, sinfo);
}
if (!ret) {
- if ( authenticator_buff.value)
- gss_release_buffer( &status, &authenticator_buff );
+ if ( authenticator_buff.value)
+ gss_release_buffer( &status, &authenticator_buff );
gss_release_cred( &status, &server_creds );
cleanup_vars:
gss_release_name( &status, &server_name );
gss_release_cred( &status, &server_creds );
cleanup_vars:
gss_release_name( &status, &server_name );
return ret;
}
/* -------------------------- */
static int gss_login(void *obj, struct passwd **uam_pwd,
return ret;
}
/* -------------------------- */
static int gss_login(void *obj, struct passwd **uam_pwd,
- char *ibuf, int ibuflen,
- char *rbuf, int *rbuflen)
+ char *ibuf, int ibuflen,
+ char *rbuf, int *rbuflen)
- char *ibuf, int ibuflen,
- char *rbuf, int *rbuflen)
+ char *ibuf, int ibuflen,
+ char *rbuf, int *rbuflen)
* pad (byte) [consumed before login_ext is called]
* ?? (byte) - always observed to be 0
* id returned in LoginExt response (u_int16_t)
* pad (byte) [consumed before login_ext is called]
* ?? (byte) - always observed to be 0
* id returned in LoginExt response (u_int16_t)
- * username, encoding unspecified, null terminated C string,
+ * username, encoding unspecified, null terminated C string,
* odd numbered byte. Eg if the username is 3 characters and the
* terminating null makes 4, expect to pad the the result.
* The encoding of this string is unknown.
* odd numbered byte. Eg if the username is 3 characters and the
* terminating null makes 4, expect to pad the the result.
* The encoding of this string is unknown.
/* get the session_info structure from afpd. We need the session key */
if (uam_afpserver_option(obj, UAM_OPTION_SESSIONINFO, (void *)&sinfo, NULL) < 0)
/* get the session_info structure from afpd. We need the session key */
if (uam_afpserver_option(obj, UAM_OPTION_SESSIONINFO, (void *)&sinfo, NULL) < 0)
if (sinfo->sessionkey == NULL || sinfo->sessionkey_len == 0) {
/* Should never happen. Most likely way too old afpd version */
if (sinfo->sessionkey == NULL || sinfo->sessionkey_len == 0) {
/* Should never happen. Most likely way too old afpd version */
while( *ibuf && ibuflen ) { ibuf++, ibuflen--; }
if (ibuflen < 4) {
LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: user is %s, no ticket", p);
while( *ibuf && ibuflen ) { ibuf++, ibuflen--; }
if (ibuflen < 4) {
LOG(log_info, logtype_uams, "uams_gss.c :LoginCont: user is %s, no ticket", p);
if (ticket_len > ibuflen) {
LOG(log_info, logtype_uams,
"uams_gss.c :LoginCont: invalid ticket length (%u > %u)", ticket_len, ibuflen);
if (ticket_len > ibuflen) {
LOG(log_info, logtype_uams,
"uams_gss.c :LoginCont: invalid ticket length (%u > %u)", ticket_len, ibuflen);
Should we compare this to the username the client sent in the clear?
We know the character encoding of the cleartext username (UTF8), what
encoding is the gssapi name in? */
Should we compare this to the username the client sent in the clear?
We know the character encoding of the cleartext username (UTF8), what
encoding is the gssapi name in? */
- if((pwd = uam_getname( obj, username, userlen )) == NULL) {
- LOG(log_info, logtype_uams, "uam_getname() failed for %s", username);
- return AFPERR_PARAM;
- }
- if (uam_checkuser(pwd) < 0) {
- LOG(log_info, logtype_uams, "%s not a valid user", username);
- return AFPERR_NOTAUTH;
- }
- *rbuflen = rblen;
- *uam_pwd = pwd;
- return AFP_OK;
+ if((pwd = uam_getname( obj, username, userlen )) == NULL) {
+ LOG(log_info, logtype_uams, "uam_getname() failed for %s", username);
+ return AFPERR_PARAM;
+ }
+ if (uam_checkuser(pwd) < 0) {
+ LOG(log_info, logtype_uams, "%s not a valid user", username);
+ return AFPERR_NOTAUTH;
+ }
+ *rbuflen = rblen;
+ *uam_pwd = pwd;
+ return AFP_OK;
* point is trustworthy as we'll have a signed ticket to parse in logincont.
*/
static int gss_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
* point is trustworthy as we'll have a signed ticket to parse in logincont.
*/
static int gss_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
- char *ibuf, int ibuflen,
- char *rbuf, int *rbuflen)
+ char *ibuf, int ibuflen,
+ char *rbuf, int *rbuflen)
- if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Client Krb v2",
- gss_login, gss_logincont, gss_logout, gss_login_ext) < 0)
- if (uam_register(UAM_SERVER_LOGIN, path, "Client Krb v2",
- gss_login, gss_logincont, gss_logout) < 0)
- return -1;
+ if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Client Krb v2",
+ gss_login, gss_logincont, gss_logout, gss_login_ext) < 0)
+ if (uam_register(UAM_SERVER_LOGIN, path, "Client Krb v2",
+ gss_login, gss_logincont, gss_logout) < 0)
+ return -1;