Skip to content

Commit

Permalink
kerberos and gssapi support
Browse files Browse the repository at this point in the history
Initial implementation of GSSAPIv1 support.
KRB5 authentication is supported.
KRB5I and KRB5P is not supported.

Signed-off-by: sahlberg <[email protected]>
  • Loading branch information
sahlberg committed Feb 17, 2024
1 parent 3f9452e commit e806051
Show file tree
Hide file tree
Showing 21 changed files with 1,733 additions and 352 deletions.
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ if(ENABLE_TESTS)
endif()

include(cmake/Macros.cmake)

if(IOS)
find_package(GSSAPI)

if(GSSAPI_FOUND)
add_definitions(-DHAVE_LIBKRB5)
endif()
endif()

include(cmake/ConfigureChecks.cmake)

include_directories(${CMAKE_CURRENT_BINARY_DIR}
Expand Down
3 changes: 2 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ URL-FORMAT:
Libnfs uses RFC2224 style URLs extended with some minor libnfs extensions.
The basic syntax of these URLs is :

nfs://<server|ipv4|ipv6>[:<port>]/path[?arg=val[&arg=val]*]
nfs://[<username>@]<server|ipv4|ipv6>[:<port>]/path[?arg=val[&arg=val]*]

Special characters in 'path' are escaped using %-hex-hex syntax.

Expand All @@ -77,6 +77,7 @@ Arguments supported by libnfs are :
default it 65534 on Windows and getuid() on unixen.
gid=<int> : GID value to use when talking to the server.
default it 65534 on Windows and getgid() on unixen.
sec=<krb5> : Specify the security mode.
auto-traverse-mounts=<0|1>
: Should libnfs try to traverse across nested mounts
automatically or not. Default is 1 == enabled.
Expand Down
18 changes: 18 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ AC_ARG_ENABLE([examples],
[ENABLE_EXAMPLES=$enableval],
[ENABLE_EXAMPLES="no"])

AC_ARG_WITH([libkrb5],
[AS_HELP_STRING([--without-libkrb5],
[Do not link with libkrb5 even if available.])])
AS_IF([test "x$with_libkrb5" != "xno"], [
MAYBE_LIBKRB5="-lgssapi_krb5"
AC_DEFINE([HAVE_LIBKRB5], [1], [Whether we use gssapi_krb5 or not])
AC_MSG_NOTICE([Build with gssapi_krb5 support])
dnl Check for gssapi/gssapi.h
AC_CHECK_HEADERS([gssapi/gssapi.h], [], [
AC_MSG_ERROR([You need gssapi development files to compile libsmb2.])
])
], [
MAYBE_LIBKRB5=""
AC_MSG_NOTICE([Build WITHOUT gssapi_krb5 support])
])

# We need popt to compile the examples
if test x$ENABLE_EXAMPLES = xyes; then
AC_MSG_CHECKING(whether libpopt is available)
Expand Down Expand Up @@ -119,6 +135,8 @@ else
AC_MSG_NOTICE(Compiling without getpwnam() support.)
fi

AC_SUBST([MAYBE_LIBKRB5])

AC_ARG_ENABLE([werror], [AS_HELP_STRING([--disable-werror],
[Disables building with -Werror by default])])

Expand Down
17 changes: 17 additions & 0 deletions include/libnfs-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ enum input_state {
READ_UNKNOWN = 5,
};

struct gss_ctx_id_struct;
struct rpc_context {
uint32_t magic;
int fd;
Expand Down Expand Up @@ -194,6 +195,18 @@ struct rpc_context {
char ifname[IFNAMSIZ];
int poll_timeout;

#ifdef HAVE_LIBKRB5
const char *username;
enum rpc_sec wanted_sec;
enum rpc_sec sec;
uint32_t gss_seqno;
int context_len;
char *context;

void *auth_data; /* for krb5 */
struct gss_ctx_id_struct *gss_context;
#endif /* HAVE_LIBKRB5 */

/* Is a server context ? */
int is_server_context;
struct rpc_endpoint *endpoints;
Expand Down Expand Up @@ -235,6 +248,10 @@ struct rpc_pdu {
uint32_t flags;

uint64_t timeout;
#ifdef HAVE_LIBKRB5
uint32_t gss_seqno;
char creds[64];
#endif
};

void rpc_reset_queue(struct rpc_queue *q);
Expand Down
6 changes: 5 additions & 1 deletion include/nfsc/libnfs-raw.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ EXTERN void rpc_set_uid(struct rpc_context *rpc, int uid);
EXTERN void rpc_set_gid(struct rpc_context *rpc, int gid);
EXTERN void rpc_set_auxiliary_gids(struct rpc_context *rpc, uint32_t len, uint32_t* gids);

/*
* Used in GSSAPI mode
*/
EXTERN int rpc_set_username(struct rpc_context *rpc, const char *username);

/*
* Create a server context.
*/
Expand Down Expand Up @@ -2480,7 +2485,6 @@ EXTERN struct rpc_pdu *
rpc_null_task(struct rpc_context *rpc, int program, int version,
rpc_cb cb, void *private_data);


#ifdef __cplusplus
}
#endif
Expand Down
31 changes: 24 additions & 7 deletions include/nfsc/libnfs-zdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,28 @@ typedef uint32_t (*zdrproc_t) (ZDR *, void *,...);
#define AUTH_NULL 0
#define AUTH_SYS 1
#define AUTH_UNIX 1
#define AUTH_GSS 6

struct opaque_auth {
struct opaque_cred {
uint32_t oa_flavor;
caddr_t oa_base;
uint32_t oa_length;
};
extern struct opaque_auth _null_auth;

struct gss_ctx_id_struct;
struct opaque_verf {
uint32_t oa_flavor;
caddr_t oa_base;
uint32_t oa_length;

/* GSS */
struct gss_ctx_id_struct *gss_context;
};
extern struct opaque_verf _null_auth;

struct AUTH {
struct opaque_auth ah_cred;
struct opaque_auth ah_verf;
struct opaque_cred ah_cred;
struct opaque_verf ah_verf;
caddr_t ah_private;
};

Expand Down Expand Up @@ -168,13 +179,13 @@ struct call_body {
uint32_t prog;
uint32_t vers;
uint32_t proc;
struct opaque_auth cred;
struct opaque_auth verf;
struct opaque_cred cred;
struct opaque_verf verf;
void *args;
};

struct accepted_reply {
struct opaque_auth verf;
struct opaque_verf verf;
uint32_t stat;
union {
struct {
Expand Down Expand Up @@ -267,6 +278,9 @@ bool_t libnfs_zdr_setpos(ZDR *zdrs, uint32_t pos);
#define zdr_getpos libnfs_zdr_getpos
uint32_t libnfs_zdr_getpos(ZDR *zdrs);

#define zdr_getptr libnfs_zdr_getptr
char *libnfs_zdr_getptr(ZDR *zdrs);

#define zdr_free libnfs_zdr_free
void libnfs_zdr_free(zdrproc_t proc, char *objp);

Expand All @@ -287,6 +301,9 @@ struct AUTH *libnfs_authunix_create(const char *host, uint32_t uid, uint32_t gid
#define authunix_create_default libnfs_authunix_create_default
struct AUTH *libnfs_authunix_create_default(void);

int libnfs_authgss_init(struct rpc_context *rpc);
int libnfs_authgss_gen_creds(struct rpc_context *rpc, ZDR *zdr);

#define auth_destroy libnfs_auth_destroy
void libnfs_auth_destroy(struct AUTH *auth);

Expand Down
12 changes: 12 additions & 0 deletions include/nfsc/libnfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,18 @@ EXTERN int nfs_queue_length(struct nfs_context *nfs);
struct AUTH;
EXTERN void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth);

/*
* Used to set which security to use.
*/
enum rpc_sec {
RPC_SEC_UNDEFINED = 0,
RPC_SEC_KRB5,
//RPC_SEC_KRB5I,
//RPC_SEC_KRB5P,
};
EXTERN void nfs_set_security(struct nfs_context *nfs, enum rpc_sec sec);


/*
* Used if you need to bind to a specific interface.
* Only available on platforms that support SO_BINDTODEVICE.
Expand Down
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
set(SOURCES init.c
krb5-wrapper.c
libnfs.c
libnfs-sync.c
libnfs-zdr.c
Expand Down
4 changes: 3 additions & 1 deletion lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ libnfs_la_CPPFLAGS = -I$(abs_top_srcdir)/include \

libnfs_la_SOURCES = \
init.c \
krb5-wrapper.c \
libnfs.c \
libnfs-sync.c \
libnfs-zdr.c \
Expand All @@ -29,7 +30,8 @@ libnfs_la_SOURCES = \
SOCURRENT=14
SOREVISION=0
SOAGE=0
libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE)
libnfs_la_LDFLAGS = -version-info $(SOCURRENT):$(SOREVISION):$(SOAGE) \
$(MAYBE_LIBKRB5)
if HAVE_WIN32
libnfs_la_LDFLAGS += -no-undefined
endif
Expand Down
23 changes: 23 additions & 0 deletions lib/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@
#include "libnfs-raw.h"
#include "libnfs-private.h"

#ifdef HAVE_LIBKRB5
#include "krb5-wrapper.h"
#endif

#ifndef discard_const
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
#endif

uint64_t rpc_current_time(void)
{
#ifdef HAVE_CLOCK_GETTIME
Expand Down Expand Up @@ -220,6 +228,15 @@ struct rpc_context *rpc_init_udp_context(void)
return rpc;
}

int rpc_set_username(struct rpc_context *rpc, const char *username)
{
#ifdef HAVE_LIBKRB5
free(discard_const(rpc->username));
rpc->username = strdup(username);
#endif
return 0;
}

void rpc_set_auth(struct rpc_context *rpc, struct AUTH *auth)
{
assert(rpc->magic == RPC_CONTEXT_MAGIC);
Expand Down Expand Up @@ -431,6 +448,12 @@ void rpc_destroy_context(struct rpc_context *rpc)
#ifdef HAVE_MULTITHREADING
nfs_mt_mutex_destroy(&rpc->rpc_mutex);
#endif /* HAVE_MULTITHREADING */
#ifdef HAVE_LIBKRB5
if (rpc->auth_data) {
krb5_free_auth_data(rpc->auth_data);
}
free(discard_const(rpc->username));
#endif
free(rpc);
}

Expand Down
Loading

0 comments on commit e806051

Please sign in to comment.