2007-12-05 18:23:39 +03:00
/*
2008-07-16 17:27:05 -07:00
* CIFS user - space helper .
2007-12-05 18:23:39 +03:00
* Copyright ( C ) Igor Mammedov ( niallain @ gmail . com ) 2007
2009-07-09 21:04:08 -04:00
* Copyright ( C ) Jeff Layton ( jlayton @ redhat . com ) 2009
2007-12-05 18:23:39 +03:00
*
* Used by / sbin / request - key for handling
2007-12-19 17:48:43 +03:00
* cifs upcall for kerberos authorization of access to share and
* cifs upcall for DFS srver name resolving ( IPv4 / IPv6 aware ) .
2008-08-05 13:27:07 -05:00
* You should have keyutils installed and add something like the
* following lines to / etc / request - key . conf file :
2007-12-05 18:23:39 +03:00
2008-08-05 13:27:07 -05:00
create cifs . spnego * * / usr / local / sbin / cifs . upcall % k
create dns_resolver * * / usr / local / sbin / cifs . upcall % k
2007-12-05 18:23:39 +03:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
* This program 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 General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "includes.h"
# include <keyutils.h>
# include "cifs_spnego.h"
2009-08-14 07:59:50 -04:00
const char * CIFSSPNEGO_VERSION = " 1.3 " ;
2008-07-16 17:27:05 -07:00
static const char * prog = " cifs.upcall " ;
2009-08-14 07:59:49 -04:00
typedef enum _sectype {
2008-09-12 21:13:54 -04:00
NONE = 0 ,
2007-12-05 18:23:39 +03:00
KRB5 ,
MS_KRB5
2009-08-14 07:59:49 -04:00
} sectype_t ;
2007-12-05 18:23:39 +03:00
2009-07-09 21:04:08 -04:00
/*
* given a process ID , get the value of the KRB5CCNAME environment variable
* in the context of that process . On error , just return NULL .
*/
static char *
get_krb5_ccname ( pid_t pid )
{
int fd ;
ssize_t len , left ;
/*
* FIXME : sysconf for ARG_MAX instead ? Kernel seems to be limited to a
* page however , so it may not matter .
*/
char buf [ 4096 ] ;
char * p , * value = NULL ;
buf [ 4095 ] = ' \0 ' ;
snprintf ( buf , 4095 , " /proc/%d/environ " , pid ) ;
fd = open ( buf , O_RDONLY ) ;
2009-08-14 07:59:49 -04:00
if ( fd < 0 ) {
syslog ( LOG_DEBUG , " %s: unable to open %s: %d " , __func__ , buf ,
errno ) ;
2009-07-09 21:04:08 -04:00
return NULL ;
2009-08-14 07:59:49 -04:00
}
2009-07-09 21:04:08 -04:00
/* FIXME: don't assume that we get it all in the first read? */
len = read ( fd , buf , 4096 ) ;
close ( fd ) ;
2009-08-14 07:59:49 -04:00
if ( len < 0 ) {
syslog ( LOG_DEBUG , " %s: unable to read from /proc/%d/environ: "
" %d " , __func__ , pid , errno ) ;
2009-07-09 21:04:08 -04:00
return NULL ;
2009-08-14 07:59:49 -04:00
}
2009-07-09 21:04:08 -04:00
left = len ;
p = buf ;
/* can't have valid KRB5CCNAME if there are < 13 bytes left */
while ( left > 12 ) {
if ( strncmp ( " KRB5CCNAME= " , p , 11 ) ) {
p + = strnlen ( p , left ) ;
+ + p ;
left = buf + len - p ;
continue ;
}
p + = 11 ;
left - = 11 ;
2009-07-10 11:59:00 +02:00
value = SMB_STRNDUP ( p , left ) ;
2009-07-09 21:04:08 -04:00
break ;
}
2009-08-14 07:59:49 -04:00
syslog ( LOG_DEBUG , " %s: KRB5CCNAME=%s " , __func__ ,
value ? value : " (null) " ) ;
2009-07-09 21:04:08 -04:00
return value ;
}
2007-12-05 18:23:39 +03:00
/*
* Prepares AP - REQ data for mechToken and gets session key
* Uses credentials from cache . It will not ask for password
* you should receive credentials for yuor name manually using
* kinit or whatever you wish .
*
* in :
* oid - string with OID / Could be OID_KERBEROS5
* or OID_KERBEROS5_OLD
* principal - Service name .
* Could be " cifs/FQDN " for KRB5 OID
* or for MS_KRB5 OID style server principal
* like " pdc$@YOUR.REALM.NAME "
*
* out :
* secblob - pointer for spnego wrapped AP - REQ data to be stored
* sess_key - pointer for SessionKey data to be stored
*
* ret : 0 - success , others - failure
2009-08-14 07:59:49 -04:00
*/
2008-09-12 21:13:54 -04:00
static int
2009-07-09 21:04:08 -04:00
handle_krb5_mech ( const char * oid , const char * principal , DATA_BLOB * secblob ,
DATA_BLOB * sess_key , const char * ccname )
2007-12-05 18:23:39 +03:00
{
int retval ;
DATA_BLOB tkt , tkt_wrapped ;
2009-08-14 07:59:49 -04:00
syslog ( LOG_DEBUG , " %s: getting service ticket for %s " , __func__ ,
principal ) ;
2007-12-05 18:23:39 +03:00
/* get a kerberos ticket for the service and extract the session key */
2009-07-09 21:04:08 -04:00
retval = cli_krb5_get_ticket ( principal , 0 , & tkt , sess_key , 0 , ccname ,
NULL ) ;
2007-12-05 18:23:39 +03:00
2009-08-14 07:59:49 -04:00
if ( retval ) {
syslog ( LOG_DEBUG , " %s: failed to obtain service ticket (%d) " ,
__func__ , retval ) ;
2007-12-05 18:23:39 +03:00
return retval ;
2009-08-14 07:59:49 -04:00
}
syslog ( LOG_DEBUG , " %s: obtained service ticket " , __func__ ) ;
2007-12-05 18:23:39 +03:00
/* wrap that up in a nice GSS-API wrapping */
tkt_wrapped = spnego_gen_krb5_wrap ( tkt , TOK_ID_KRB_AP_REQ ) ;
/* and wrap that in a shiny SPNEGO wrapper */
2008-08-19 21:29:41 -04:00
* secblob = gen_negTokenInit ( oid , tkt_wrapped ) ;
2007-12-05 18:23:39 +03:00
data_blob_free ( & tkt_wrapped ) ;
data_blob_free ( & tkt ) ;
return retval ;
}
2009-08-14 07:59:49 -04:00
# define DKD_HAVE_HOSTNAME 0x1
# define DKD_HAVE_VERSION 0x2
# define DKD_HAVE_SEC 0x4
2009-08-14 07:59:50 -04:00
# define DKD_HAVE_IP 0x8
# define DKD_HAVE_UID 0x10
# define DKD_HAVE_PID 0x20
# define DKD_MUSTHAVE_SET (DKD_HAVE_IP|DKD_HAVE_VERSION|DKD_HAVE_SEC)
2007-12-05 18:23:39 +03:00
2009-08-14 07:59:49 -04:00
static struct decoded_args {
int ver ;
char * hostname ;
2009-08-14 07:59:50 -04:00
char * ip ;
2009-08-14 07:59:49 -04:00
uid_t uid ;
pid_t pid ;
sectype_t sec ;
} ;
2009-08-14 07:59:50 -04:00
static unsigned int
2009-08-14 07:59:49 -04:00
decode_key_description ( const char * desc , struct decoded_args * arg )
2007-12-05 18:23:39 +03:00
{
2009-08-14 07:59:50 -04:00
int len ;
2007-12-05 18:23:39 +03:00
int retval = 0 ;
char * pos ;
const char * tkn = desc ;
do {
pos = index ( tkn , ' ; ' ) ;
if ( strncmp ( tkn , " host= " , 5 ) = = 0 ) {
2009-08-14 07:59:49 -04:00
if ( pos = = NULL )
2007-12-05 18:23:39 +03:00
len = strlen ( tkn ) ;
2009-08-14 07:59:49 -04:00
else
2007-12-05 18:23:39 +03:00
len = pos - tkn ;
2009-08-14 07:59:49 -04:00
2007-12-05 18:23:39 +03:00
len - = 4 ;
2009-08-14 07:59:49 -04:00
SAFE_FREE ( arg - > hostname ) ;
arg - > hostname = SMB_XMALLOC_ARRAY ( char , len ) ;
strlcpy ( arg - > hostname , tkn + 5 , len ) ;
2007-12-05 18:23:39 +03:00
retval | = DKD_HAVE_HOSTNAME ;
2009-08-14 07:59:50 -04:00
} else if ( ! strncmp ( tkn , " ip4= " , 4 ) | |
! strncmp ( tkn , " ip6= " , 4 ) ) {
if ( pos = = NULL )
len = strlen ( tkn ) ;
else
len = pos - tkn ;
len - = 3 ;
SAFE_FREE ( arg - > ip ) ;
arg - > ip = SMB_XMALLOC_ARRAY ( char , len ) ;
strlcpy ( arg - > ip , tkn + 4 , len ) ;
retval | = DKD_HAVE_IP ;
2009-07-09 21:04:08 -04:00
} else if ( strncmp ( tkn , " pid= " , 4 ) = = 0 ) {
errno = 0 ;
2009-08-14 07:59:49 -04:00
arg - > pid = strtol ( tkn + 4 , NULL , 0 ) ;
2009-07-09 21:04:08 -04:00
if ( errno ! = 0 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " Invalid pid format: %s " ,
2009-07-09 21:04:08 -04:00
strerror ( errno ) ) ;
return 1 ;
} else {
retval | = DKD_HAVE_PID ;
}
2007-12-05 18:23:39 +03:00
} else if ( strncmp ( tkn , " sec= " , 4 ) = = 0 ) {
if ( strncmp ( tkn + 4 , " krb5 " , 4 ) = = 0 ) {
retval | = DKD_HAVE_SEC ;
2009-08-14 07:59:49 -04:00
arg - > sec = KRB5 ;
2008-08-19 21:29:41 -04:00
} else if ( strncmp ( tkn + 4 , " mskrb5 " , 6 ) = = 0 ) {
retval | = DKD_HAVE_SEC ;
2009-08-14 07:59:49 -04:00
arg - > sec = MS_KRB5 ;
2007-12-05 18:23:39 +03:00
}
} else if ( strncmp ( tkn , " uid= " , 4 ) = = 0 ) {
errno = 0 ;
2009-08-14 07:59:49 -04:00
arg - > uid = strtol ( tkn + 4 , NULL , 16 ) ;
2007-12-05 18:23:39 +03:00
if ( errno ! = 0 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " Invalid uid format: %s " ,
2007-12-05 18:23:39 +03:00
strerror ( errno ) ) ;
return 1 ;
} else {
retval | = DKD_HAVE_UID ;
}
} else if ( strncmp ( tkn , " ver= " , 4 ) = = 0 ) { /* if version */
errno = 0 ;
2009-08-14 07:59:49 -04:00
arg - > ver = strtol ( tkn + 4 , NULL , 16 ) ;
2007-12-05 18:23:39 +03:00
if ( errno ! = 0 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " Invalid version format: %s " ,
2007-12-05 18:23:39 +03:00
strerror ( errno ) ) ;
return 1 ;
} else {
retval | = DKD_HAVE_VERSION ;
}
}
if ( pos = = NULL )
break ;
tkn = pos + 1 ;
} while ( tkn ) ;
return retval ;
}
2008-09-12 21:13:54 -04:00
static int
cifs_resolver ( const key_serial_t key , const char * key_descr )
2007-12-19 17:48:43 +03:00
{
int c ;
struct addrinfo * addr ;
char ip [ INET6_ADDRSTRLEN ] ;
void * p ;
const char * keyend = key_descr ;
/* skip next 4 ';' delimiters to get to description */
for ( c = 1 ; c < = 4 ; c + + ) {
keyend = index ( keyend + 1 , ' ; ' ) ;
if ( ! keyend ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " invalid key description: %s " ,
2007-12-19 17:48:43 +03:00
key_descr ) ;
return 1 ;
}
}
keyend + + ;
/* resolve name to ip */
c = getaddrinfo ( keyend , NULL , NULL , & addr ) ;
if ( c ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " unable to resolve hostname: %s [%s] " ,
2007-12-19 17:48:43 +03:00
keyend , gai_strerror ( c ) ) ;
return 1 ;
}
/* conver ip to string form */
2009-08-14 07:59:49 -04:00
if ( addr - > ai_family = = AF_INET )
2007-12-19 17:48:43 +03:00
p = & ( ( ( struct sockaddr_in * ) addr - > ai_addr ) - > sin_addr ) ;
2009-08-14 07:59:49 -04:00
else
2007-12-19 17:48:43 +03:00
p = & ( ( ( struct sockaddr_in6 * ) addr - > ai_addr ) - > sin6_addr ) ;
2009-08-14 07:59:49 -04:00
2007-12-19 17:48:43 +03:00
if ( ! inet_ntop ( addr - > ai_family , p , ip , sizeof ( ip ) ) ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " %s: inet_ntop: %s " , __func__ , strerror ( errno ) ) ;
2007-12-19 17:48:43 +03:00
freeaddrinfo ( addr ) ;
return 1 ;
}
/* setup key */
c = keyctl_instantiate ( key , ip , strlen ( ip ) + 1 , 0 ) ;
if ( c = = - 1 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " %s: keyctl_instantiate: %s " , __func__ ,
strerror ( errno ) ) ;
2007-12-19 17:48:43 +03:00
freeaddrinfo ( addr ) ;
return 1 ;
}
freeaddrinfo ( addr ) ;
return 0 ;
}
2009-08-14 07:59:50 -04:00
static int
ip_to_fqdn ( const char * ipaddr , char * host , size_t hostlen )
{
int rc ;
struct addrinfo hints = { . ai_flags = AI_NUMERICHOST } ;
struct addrinfo * res ;
rc = getaddrinfo ( ipaddr , NULL , & hints , & res ) ;
if ( rc ) {
syslog ( LOG_DEBUG , " %s: failed to resolve %s to ipaddr: %s " ,
__func__ , ipaddr ,
rc = = EAI_SYSTEM ? strerror ( errno ) : gai_strerror ( rc ) ) ;
return rc ;
}
rc = getnameinfo ( res - > ai_addr , res - > ai_addrlen , host , hostlen ,
NULL , 0 , NI_NAMEREQD ) ;
freeaddrinfo ( res ) ;
if ( rc ) {
syslog ( LOG_DEBUG , " %s: failed to resolve %s to fqdn: %s " ,
__func__ , ipaddr ,
rc = = EAI_SYSTEM ? strerror ( errno ) : gai_strerror ( rc ) ) ;
return rc ;
}
syslog ( LOG_DEBUG , " %s: resolved %s to %s " , __func__ , ipaddr , host ) ;
return 0 ;
}
2008-09-12 21:13:54 -04:00
static void
2008-08-05 15:36:11 -05:00
usage ( void )
2008-07-16 17:27:05 -07:00
{
2009-08-14 07:59:50 -04:00
syslog ( LOG_INFO , " Usage: %s [-v] key_serial " , prog ) ;
fprintf ( stderr , " Usage: %s [-v] key_serial \n " , prog ) ;
2008-07-16 17:27:05 -07:00
}
2007-12-05 18:23:39 +03:00
int main ( const int argc , char * const argv [ ] )
{
2007-12-05 17:54:09 -05:00
struct cifs_spnego_msg * keydata = NULL ;
2007-12-05 18:23:39 +03:00
DATA_BLOB secblob = data_blob_null ;
DATA_BLOB sess_key = data_blob_null ;
2008-08-12 14:32:54 -04:00
key_serial_t key = 0 ;
2007-12-05 18:23:39 +03:00
size_t datalen ;
2009-08-14 07:59:50 -04:00
unsigned int have ;
2007-12-05 18:23:39 +03:00
long rc = 1 ;
2009-08-14 07:59:50 -04:00
int c ;
2009-08-14 07:59:49 -04:00
char * buf , * princ , * ccname = NULL ;
2009-08-14 07:59:50 -04:00
char hostbuf [ NI_MAXHOST ] ;
2009-08-14 07:59:49 -04:00
struct decoded_args arg = { } ;
2008-08-21 21:21:48 -04:00
const char * oid ;
2007-12-05 18:23:39 +03:00
openlog ( prog , 0 , LOG_DAEMON ) ;
while ( ( c = getopt ( argc , argv , " cv " ) ) ! = - 1 ) {
switch ( c ) {
2009-08-14 07:59:49 -04:00
case ' c ' :
2009-08-14 07:59:50 -04:00
/* legacy option -- skip it */
2007-12-05 18:23:39 +03:00
break ;
2009-08-14 07:59:49 -04:00
case ' v ' :
2008-07-16 17:27:05 -07:00
printf ( " version: %s \n " , CIFSSPNEGO_VERSION ) ;
goto out ;
2009-08-14 07:59:49 -04:00
default :
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " unknown option: %c " , c ) ;
2007-12-05 18:23:39 +03:00
goto out ;
}
}
2008-07-16 17:27:05 -07:00
/* is there a key? */
if ( argc < = optind ) {
2008-07-23 14:25:17 -05:00
usage ( ) ;
2008-07-16 17:27:05 -07:00
goto out ;
}
2007-12-05 18:23:39 +03:00
/* get key and keyring values */
errno = 0 ;
key = strtol ( argv [ optind ] , NULL , 10 ) ;
if ( errno ! = 0 ) {
2008-08-12 14:32:54 -04:00
key = 0 ;
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " Invalid key format: %s " , strerror ( errno ) ) ;
2007-12-05 18:23:39 +03:00
goto out ;
}
rc = keyctl_describe_alloc ( key , & buf ) ;
if ( rc = = - 1 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " keyctl_describe_alloc failed: %s " ,
2007-12-05 18:23:39 +03:00
strerror ( errno ) ) ;
rc = 1 ;
goto out ;
}
2009-08-14 07:59:49 -04:00
syslog ( LOG_DEBUG , " key description: %s " , buf ) ;
2008-07-24 09:32:53 -05:00
if ( ( strncmp ( buf , " cifs.resolver " , sizeof ( " cifs.resolver " ) - 1 ) = = 0 ) | |
( strncmp ( buf , " dns_resolver " , sizeof ( " dns_resolver " ) - 1 ) = = 0 ) ) {
2007-12-19 17:48:43 +03:00
rc = cifs_resolver ( key , buf ) ;
goto out ;
}
2009-08-14 07:59:50 -04:00
have = decode_key_description ( buf , & arg ) ;
SAFE_FREE ( buf ) ;
if ( ( have & DKD_MUSTHAVE_SET ) ! = DKD_MUSTHAVE_SET ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " unable to get necessary params from key "
2009-08-14 07:59:50 -04:00
" description (0x%x) " , have ) ;
2007-12-05 18:23:39 +03:00
rc = 1 ;
goto out ;
}
2009-08-14 07:59:49 -04:00
if ( arg . ver > CIFS_SPNEGO_UPCALL_VERSION ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " incompatible kernel upcall version: 0x%x " ,
2009-08-14 07:59:49 -04:00
arg . ver ) ;
2007-12-05 18:23:39 +03:00
rc = 1 ;
goto out ;
}
2009-08-14 07:59:50 -04:00
if ( have & DKD_HAVE_UID ) {
2009-08-14 07:59:49 -04:00
rc = setuid ( arg . uid ) ;
2007-12-05 18:23:39 +03:00
if ( rc = = - 1 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " setuid: %s " , strerror ( errno ) ) ;
2007-12-05 18:23:39 +03:00
goto out ;
}
}
2009-08-14 07:59:50 -04:00
if ( have & DKD_HAVE_PID )
ccname = get_krb5_ccname ( arg . pid ) ;
2009-08-14 07:59:50 -04:00
if ( have & DKD_HAVE_IP ) {
rc = ip_to_fqdn ( arg . ip , hostbuf , sizeof ( hostbuf ) ) ;
if ( rc )
goto out ;
}
2007-12-05 18:23:39 +03:00
// do mech specific authorization
2009-08-14 07:59:49 -04:00
switch ( arg . sec ) {
2008-08-19 21:29:41 -04:00
case MS_KRB5 :
2009-08-14 07:59:49 -04:00
case KRB5 :
/* for "cifs/" service name + terminating 0 */
2009-08-14 07:59:50 -04:00
datalen = strnlen ( hostbuf , sizeof ( hostbuf ) ) + 5 + 1 ;
2009-08-14 07:59:49 -04:00
princ = SMB_XMALLOC_ARRAY ( char , datalen ) ;
if ( ! princ ) {
2007-12-05 18:23:39 +03:00
rc = 1 ;
break ;
}
2009-08-14 07:59:49 -04:00
2009-08-14 07:59:49 -04:00
if ( arg . sec = = MS_KRB5 )
2009-08-14 07:59:49 -04:00
oid = OID_KERBEROS5_OLD ;
else
oid = OID_KERBEROS5 ;
2009-08-14 07:59:50 -04:00
/*
* try getting a cifs / principal first and then fall back to
* getting a host / principal if that doesn ' t work .
*/
strlcpy ( princ , " cifs/ " , datalen ) ;
2009-08-14 07:59:50 -04:00
strlcpy ( princ + 5 , hostbuf , datalen - 5 ) ;
2009-08-14 07:59:49 -04:00
rc = handle_krb5_mech ( oid , princ , & secblob , & sess_key , ccname ) ;
2009-08-14 07:59:50 -04:00
if ( rc ) {
memcpy ( princ , " host/ " , 5 ) ;
rc = handle_krb5_mech ( oid , princ , & secblob , & sess_key ,
ccname ) ;
}
2009-08-14 07:59:49 -04:00
SAFE_FREE ( princ ) ;
break ;
default :
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " sectype: %d is not implemented " , arg . sec ) ;
2009-08-14 07:59:49 -04:00
rc = 1 ;
break ;
2007-12-05 18:23:39 +03:00
}
2009-08-14 07:59:49 -04:00
if ( rc )
2007-12-05 18:23:39 +03:00
goto out ;
/* pack SecurityBLob and SessionKey into downcall packet */
datalen =
sizeof ( struct cifs_spnego_msg ) + secblob . length + sess_key . length ;
keydata = ( struct cifs_spnego_msg * ) SMB_XMALLOC_ARRAY ( char , datalen ) ;
if ( ! keydata ) {
rc = 1 ;
goto out ;
}
2009-08-14 07:59:49 -04:00
keydata - > version = arg . ver ;
2007-12-05 18:23:39 +03:00
keydata - > flags = 0 ;
keydata - > sesskey_len = sess_key . length ;
keydata - > secblob_len = secblob . length ;
memcpy ( & ( keydata - > data ) , sess_key . data , sess_key . length ) ;
memcpy ( & ( keydata - > data ) + keydata - > sesskey_len ,
secblob . data , secblob . length ) ;
/* setup key */
rc = keyctl_instantiate ( key , keydata , datalen , 0 ) ;
if ( rc = = - 1 ) {
2009-08-14 07:59:49 -04:00
syslog ( LOG_ERR , " keyctl_instantiate: %s " , strerror ( errno ) ) ;
2007-12-05 18:23:39 +03:00
goto out ;
}
/* BB: maybe we need use timeout for key: for example no more then
* ticket lifietime ? */
/* keyctl_set_timeout( key, 60); */
2008-08-12 14:32:54 -04:00
out :
/*
* on error , negatively instantiate the key ourselves so that we can
* make sure the kernel doesn ' t hang it off of a searchable keyring
* and interfere with the next attempt to instantiate the key .
*/
if ( rc ! = 0 & & key = = 0 )
keyctl_negate ( key , 1 , KEY_REQKEY_DEFL_DEFAULT ) ;
2007-12-05 18:23:39 +03:00
data_blob_free ( & secblob ) ;
data_blob_free ( & sess_key ) ;
2009-07-09 21:04:08 -04:00
SAFE_FREE ( ccname ) ;
2009-08-14 07:59:49 -04:00
SAFE_FREE ( arg . hostname ) ;
2007-12-05 18:23:39 +03:00
SAFE_FREE ( keydata ) ;
return rc ;
}