1/*
2 * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _NFS_NFS_GSS_H_
30#define _NFS_NFS_GSS_H_
31
32#include <gssd/gssd_mach.h>
33#include <sys/param.h>
34#include <libkern/crypto/des.h>
35
36#define RPCSEC_GSS			6
37#define	RPCSEC_GSS_VERS_1		1
38
39enum rpcsec_gss_proc {
40	RPCSEC_GSS_DATA			= 0,
41	RPCSEC_GSS_INIT			= 1,
42	RPCSEC_GSS_CONTINUE_INIT	= 2,
43	RPCSEC_GSS_DESTROY		= 3
44};
45
46enum rpcsec_gss_service {
47	RPCSEC_GSS_SVC_NONE		= 1,	// sec=krb5
48	RPCSEC_GSS_SVC_INTEGRITY	= 2,	// sec=krb5i
49	RPCSEC_GSS_SVC_PRIVACY		= 3,	// sec=krb5p
50	RPCSEC_GSS_SVC_SYS		= 4	// sec=sys (fallback)
51};
52
53/* encoded krb5 OID */
54extern u_char krb5_mech[11];
55
56/*
57 * GSS-API things
58 */
59#define GSS_S_COMPLETE			0
60#define GSS_S_CONTINUE_NEEDED		1
61
62#define GSS_MAXSEQ			0x80000000	// The biggest sequence number
63#define GSS_SVC_MAXCONTEXTS		500000		// Max contexts supported
64#define GSS_SVC_SEQWINDOW		256		// Server's sequence window
65#define GSS_CLNT_SEQLISTMAX		32		// Max length of req seq num list
66#define GSS_CLNT_SYS_VALID		300		// Valid time (sec) for failover ctx
67
68
69#define SKEYLEN	8			// length of DES key
70#define SKEYLEN3 24			// length of DES3 keyboard
71#define MAX_SKEYLEN	SKEYLEN3
72
73typedef struct {
74	uint32_t type; 		// See defines below
75	uint32_t keybytes; 	// Session key length bytes;
76	uint32_t hash_len;
77	u_char   skey[MAX_SKEYLEN];	   	// Session key;
78	union {
79		struct {
80			des_cblock  *key;
81			des_cbc_key_schedule gss_sched;
82			des_cbc_key_schedule gss_sched_Ke;
83		} des;
84		struct {
85			des_cblock		(*key)[3];
86			des_cblock		ckey[3];
87			des3_cbc_key_schedule	gss_sched;
88		} des3;
89	} ks_u;
90} gss_key_info;
91
92#define NFS_GSS_0DES	0 // Not DES or uninitialized
93#define NFS_GSS_1DES	1 // Single DES with DES_MAC_MD5
94#define NFS_GSS_3DES	2 // Triple EDE DES KD with SHA1
95
96/*
97 * The client's RPCSEC_GSS context information
98 */
99struct nfs_gss_clnt_ctx {
100	lck_mtx_t		*gss_clnt_mtx;
101	thread_t		gss_clnt_thread;	// Thread creating context
102	TAILQ_ENTRY(nfs_gss_clnt_ctx)	gss_clnt_entries;
103	uint32_t		gss_clnt_flags;		// Flag bits - see below
104	uint32_t		gss_clnt_refcnt;	// Reference count
105	uid_t			gss_clnt_uid;		// Owner of this context
106	uint32_t		gss_clnt_proc;		// Current GSS proc for cred
107	uint32_t		gss_clnt_seqnum;	// GSS sequence number
108	uint32_t		gss_clnt_service;	// Indicates krb5, krb5i or krb5p
109	u_char			*gss_clnt_handle;	// Identifies server context
110	uint32_t		gss_clnt_handle_len;	// Size of server's ctx handle
111	time_t			gss_clnt_ctime;		// When context was created
112	uint32_t		gss_clnt_seqwin;	// Server's seq num window
113	uint32_t		*gss_clnt_seqbits;	// Bitmap to track seq numbers in use
114	mach_port_t		gss_clnt_mport;		// Mach port for gssd upcall
115	u_char			*gss_clnt_verf;		// RPC verifier from server
116	char			*gss_clnt_svcname;	// Service name e.g. "nfs/big.apple.com"
117	gssd_cred		gss_clnt_cred_handle;	// Opaque cred handle from gssd
118	gssd_ctx		gss_clnt_context;	// Opaque context handle from gssd
119	u_char			*gss_clnt_token;	// GSS token exchanged via gssd & server
120	uint32_t		gss_clnt_tokenlen;	// Length of token
121	gss_key_info		gss_clnt_kinfo;		// GSS key info
122	uint32_t		gss_clnt_gssd_flags;	// Special flag bits to gssd
123	uint32_t		gss_clnt_major;		// GSS major result from gssd or server
124	uint32_t		gss_clnt_minor;		// GSS minor result from gssd or server
125};
126
127/*
128 * gss_clnt_flags
129 */
130#define GSS_CTX_COMPLETE	0x00000001	// Context is complete
131#define GSS_CTX_INVAL		0x00000002	// Context is invalid
132#define GSS_NEEDSEQ		0x00000004	// Need a sequence number
133#define GSS_NEEDCTX		0x00000008	// Need the context
134
135/*
136 * The server's RPCSEC_GSS context information
137 */
138struct nfs_gss_svc_ctx {
139	lck_mtx_t		*gss_svc_mtx;
140	LIST_ENTRY(nfs_gss_svc_ctx)	gss_svc_entries;
141	uint32_t		gss_svc_handle;		// Identifies server context to client
142	uint32_t		gss_svc_refcnt;		// Reference count
143	uint32_t		gss_svc_proc;		// Current GSS proc from cred
144	uid_t			gss_svc_uid;		// UID of this user
145	gid_t			gss_svc_gids[NGROUPS];	// GIDs of this user
146	uint32_t		gss_svc_ngroups;	// Count of gids
147	uint64_t		gss_svc_incarnation;	// Delete ctx if we exceed this + ttl value
148	uint32_t		gss_svc_seqmax;		// Current max GSS sequence number
149	uint32_t		gss_svc_seqwin;		// GSS sequence number window
150	uint32_t		*gss_svc_seqbits;	// Bitmap to track seq numbers
151	gssd_cred		gss_svc_cred_handle;	// Opaque cred handle from gssd
152	gssd_ctx			gss_svc_context;	// Opaque context handle from gssd
153	u_char			*gss_svc_token;		// GSS token exchanged via gssd & client
154	uint32_t		gss_svc_tokenlen;	// Length of token
155	gss_key_info		gss_svc_kinfo;		// Session key info
156	uint32_t		gss_svc_major;		// GSS major result from gssd
157	uint32_t		gss_svc_minor;		// GSS minor result from gssd
158};
159
160#define SVC_CTX_HASHSZ	64
161#define SVC_CTX_HASH(handle)	((handle) % SVC_CTX_HASHSZ)
162LIST_HEAD(nfs_gss_svc_ctx_hashhead, nfs_gss_svc_ctx);
163
164/*
165 * Macros to manipulate bits in the sequence window
166 */
167#define win_getbit(bits, bit)      ((bits[(bit) / 32] &   (1 << (bit) % 32)) != 0)
168#define win_setbit(bits, bit)   do { bits[(bit) / 32] |=  (1 << (bit) % 32); } while (0)
169#define win_resetbit(bits, bit) do { bits[(bit) / 32] &= ~(1 << (bit) % 32); } while (0)
170
171/*
172 * Server context stale times
173 */
174#define GSS_CTX_PEND		5 		// seconds
175#define GSS_CTX_EXPIRE		(8 * 3600)	// seconds
176#define GSS_CTX_TTL_MIN		1		// seconds
177#define GSS_TIMER_PERIOD	300		// seconds
178#define MSECS_PER_SEC		1000
179
180__BEGIN_DECLS
181
182void	nfs_gss_init(void);
183int	nfs_gss_clnt_cred_put(struct nfsreq *, struct nfsm_chain *, mbuf_t);
184int	nfs_gss_clnt_verf_get(struct nfsreq *, struct nfsm_chain *,
185		uint32_t, uint32_t, uint32_t *);
186void	nfs_gss_clnt_rpcdone(struct nfsreq *);
187int	nfs_gss_clnt_args_restore(struct nfsreq *);
188int	nfs_gss_clnt_ctx_renew(struct nfsreq *);
189void	nfs_gss_clnt_ctx_ref(struct nfsreq *, struct nfs_gss_clnt_ctx *);
190void	nfs_gss_clnt_ctx_unref(struct nfsreq *);
191void	nfs_gss_clnt_ctx_unmount(struct nfsmount *);
192int	nfs_gss_svc_cred_get(struct nfsrv_descript *, struct nfsm_chain *);
193int	nfs_gss_svc_verf_put(struct nfsrv_descript *, struct nfsm_chain *);
194int	nfs_gss_svc_ctx_init(struct nfsrv_descript *, struct nfsrv_sock *, mbuf_t *);
195int	nfs_gss_svc_prepare_reply(struct nfsrv_descript *, struct nfsm_chain *);
196int	nfs_gss_svc_protect_reply(struct nfsrv_descript *, mbuf_t);
197void	nfs_gss_svc_ctx_deref(struct nfs_gss_svc_ctx *);
198void	nfs_gss_svc_cleanup(void);
199
200__END_DECLS
201#endif /* _NFS_NFS_GSS_H_ */
202