1/*
2 * Copyright (c) 2007-2014 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 <nfs/nfs_ioctl.h>
35#include <libkern/crypto/des.h>
36
37#define RPCSEC_GSS			6
38#define	RPCSEC_GSS_VERS_1		1
39
40enum rpcsec_gss_proc {
41	RPCSEC_GSS_DATA			= 0,
42	RPCSEC_GSS_INIT			= 1,
43	RPCSEC_GSS_CONTINUE_INIT	= 2,
44	RPCSEC_GSS_DESTROY		= 3
45};
46
47enum rpcsec_gss_service {
48	RPCSEC_GSS_SVC_NONE		= 1,	// sec=krb5
49	RPCSEC_GSS_SVC_INTEGRITY	= 2,	// sec=krb5i
50	RPCSEC_GSS_SVC_PRIVACY		= 3,	// sec=krb5p
51};
52
53/* encoded krb5 OID */
54extern u_char krb5_mech[11];
55
56/*
57 * GSS-API things
58 */
59typedef uint32_t OM_uint32;
60
61#define GSS_S_COMPLETE			0
62#define GSS_S_CONTINUE_NEEDED		1
63
64/*
65 * Some "helper" definitions to make the status code macros obvious.
66 * From gssapi.h:
67 */
68#define GSS_C_CALLING_ERROR_OFFSET 24
69#define GSS_C_ROUTINE_ERROR_OFFSET 16
70#define GSS_C_SUPPLEMENTARY_OFFSET 0
71#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
72#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
73#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul)
74
75/*
76 * The macros that test status codes for error conditions.  Note that the
77 * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now
78 * evaluates its argument only once.
79 */
80#define GSS_CALLING_ERROR(x) \
81	((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
82#define GSS_ROUTINE_ERROR(x) \
83	((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
84#define GSS_SUPPLEMENTARY_INFO(x) \
85	((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
86#define GSS_ERROR(x) \
87	((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
88		(GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
89
90#define GSS_MAXSEQ			0x80000000	// The biggest sequence number
91#define GSS_SVC_MAXCONTEXTS		500000		// Max contexts supported
92#define GSS_SVC_SEQWINDOW		256		// Server's sequence window
93#define GSS_CLNT_SEQLISTMAX		32		// Max length of req seq num list
94
95#define SKEYLEN	8			// length of DES key
96#define SKEYLEN3 24			// length of DES3 keyboard
97#define MAX_SKEYLEN	SKEYLEN3
98
99#define GSS_MAX_NEG_CACHE_ENTRIES 16
100#define GSS_NEG_CACHE_TO 3
101#define GSS_PRINT_DELAY	 (8 * 3600)	// Wait day before printing the same error message
102
103typedef struct {
104	uint32_t type; 		// See defines below
105	uint32_t keybytes; 	// Session key length bytes;
106	uint32_t hash_len;
107	u_char   skey[MAX_SKEYLEN];	   	// Session key;
108	union {
109		struct {
110			des_cblock  *key;
111			des_cbc_key_schedule gss_sched;
112			des_cbc_key_schedule gss_sched_Ke;
113		} des;
114		struct {
115			des_cblock		(*key)[3];
116			des_cblock		ckey[3];
117			des3_cbc_key_schedule	gss_sched;
118		} des3;
119	} ks_u;
120} gss_key_info;
121
122#define NFS_GSS_0DES	0 // Not DES or uninitialized
123#define NFS_GSS_1DES	1 // Single DES with DES_MAC_MD5
124#define NFS_GSS_3DES	2 // Triple EDE DES KD with SHA1
125
126/*
127 * The client's RPCSEC_GSS context information
128 */
129struct nfs_gss_clnt_ctx {
130	lck_mtx_t		*gss_clnt_mtx;
131	thread_t		gss_clnt_thread;	// Thread creating context
132	TAILQ_ENTRY(nfs_gss_clnt_ctx)	gss_clnt_entries;
133	uint32_t		gss_clnt_flags;		// Flag bits - see below
134	int32_t			gss_clnt_refcnt;	// Reference count
135	kauth_cred_t		gss_clnt_cred;		// Owner of this context
136	uint8_t			*gss_clnt_principal;	// Principal to use for this credential
137	uint32_t		gss_clnt_prinlen;	// Length of principal
138	gssd_nametype		gss_clnt_prinnt;	// Name type of principal
139	char			*gss_clnt_display;	// display name of principal
140	uint32_t		gss_clnt_proc;		// Current GSS proc for cred
141	uint32_t		gss_clnt_seqnum;	// GSS sequence number
142	uint32_t		gss_clnt_service;	// Indicates krb5, krb5i or krb5p
143	uint8_t			*gss_clnt_handle;	// Identifies server context
144	uint32_t		gss_clnt_handle_len;	// Size of server's ctx handle
145	time_t			gss_clnt_nctime;	// When context was put in the negative cache
146	uint32_t		gss_clnt_seqwin;	// Server's seq num window
147	uint32_t		*gss_clnt_seqbits;	// Bitmap to track seq numbers in use
148	mach_port_t		gss_clnt_mport;		// Mach port for gssd upcall
149	uint8_t			*gss_clnt_verf;		// RPC verifier from server
150	uint8_t			*gss_clnt_svcname;	// Service name e.g. "nfs/big.apple.com"
151	uint32_t		gss_clnt_svcnamlen;	// Service name length
152	gssd_nametype		gss_clnt_svcnt;		// Service name type
153	gssd_cred		gss_clnt_cred_handle;	// Opaque cred handle from gssd
154	gssd_ctx		gss_clnt_context;	// Opaque context handle from gssd
155	uint8_t			*gss_clnt_token;	// GSS token exchanged via gssd & server
156	uint32_t		gss_clnt_tokenlen;	// Length of token
157	gss_key_info		gss_clnt_kinfo;		// GSS key info
158	uint32_t		gss_clnt_gssd_flags;	// Special flag bits to gssd
159	uint32_t		gss_clnt_major;		// GSS major result from gssd or server
160	uint32_t		gss_clnt_minor;		// GSS minor result from gssd or server
161	time_t			gss_clnt_ptime;		// When last error message was printed
162};
163
164/*
165 * gss_clnt_flags
166 */
167#define GSS_CTX_COMPLETE	0x00000001	// Context is complete
168#define GSS_CTX_INVAL		0x00000002	// Context is invalid
169#define GSS_CTX_INCOMPLETE	0x00000004	// Context needs to be inited
170#define GSS_NEEDSEQ		0x00000008	// Need a sequence number
171#define GSS_NEEDCTX		0x00000010	// Need the context
172#define GSS_CTX_NC		0x00000020	// Context is in negative cache
173#define GSS_CTX_DESTROY		0x00000040	// Context is being destroyed, don't cache
174
175/*
176 * The server's RPCSEC_GSS context information
177 */
178struct nfs_gss_svc_ctx {
179	lck_mtx_t		*gss_svc_mtx;
180	LIST_ENTRY(nfs_gss_svc_ctx)	gss_svc_entries;
181	uint32_t		gss_svc_handle;		// Identifies server context to client
182	uint32_t		gss_svc_refcnt;		// Reference count
183	uint32_t		gss_svc_proc;		// Current GSS proc from cred
184	uid_t			gss_svc_uid;		// UID of this user
185	gid_t			gss_svc_gids[NGROUPS];	// GIDs of this user
186	uint32_t		gss_svc_ngroups;	// Count of gids
187	uint64_t		gss_svc_incarnation;	// Delete ctx if we exceed this + ttl value
188	uint32_t		gss_svc_seqmax;		// Current max GSS sequence number
189	uint32_t		gss_svc_seqwin;		// GSS sequence number window
190	uint32_t		*gss_svc_seqbits;	// Bitmap to track seq numbers
191	gssd_cred		gss_svc_cred_handle;	// Opaque cred handle from gssd
192	gssd_ctx		gss_svc_context;	// Opaque context handle from gssd
193	u_char			*gss_svc_token;		// GSS token exchanged via gssd & client
194	uint32_t		gss_svc_tokenlen;	// Length of token
195	gss_key_info		gss_svc_kinfo;		// Session key info
196	uint32_t		gss_svc_major;		// GSS major result from gssd
197	uint32_t		gss_svc_minor;		// GSS minor result from gssd
198};
199
200#define SVC_CTX_HASHSZ	64
201#define SVC_CTX_HASH(handle)	((handle) % SVC_CTX_HASHSZ)
202LIST_HEAD(nfs_gss_svc_ctx_hashhead, nfs_gss_svc_ctx);
203
204/*
205 * Macros to manipulate bits in the sequence window
206 */
207#define win_getbit(bits, bit)      ((bits[(bit) / 32] &   (1 << (bit) % 32)) != 0)
208#define win_setbit(bits, bit)   do { bits[(bit) / 32] |=  (1 << (bit) % 32); } while (0)
209#define win_resetbit(bits, bit) do { bits[(bit) / 32] &= ~(1 << (bit) % 32); } while (0)
210
211/*
212 * Server context stale times
213 */
214#define GSS_CTX_PEND		5 		// seconds
215#define GSS_CTX_EXPIRE		(8 * 3600)	// seconds
216#define GSS_CTX_TTL_MIN		1		// seconds
217#define GSS_TIMER_PERIOD	300		// seconds
218#define MSECS_PER_SEC		1000
219
220__BEGIN_DECLS
221
222void	nfs_gss_init(void);
223int	nfs_gss_clnt_cred_put(struct nfsreq *, struct nfsm_chain *, mbuf_t);
224int	nfs_gss_clnt_verf_get(struct nfsreq *, struct nfsm_chain *,
225		uint32_t, uint32_t, uint32_t *);
226void	nfs_gss_clnt_rpcdone(struct nfsreq *);
227int	nfs_gss_clnt_args_restore(struct nfsreq *);
228int	nfs_gss_clnt_ctx_renew(struct nfsreq *);
229void	nfs_gss_clnt_ctx_ref(struct nfsreq *, struct nfs_gss_clnt_ctx *);
230void	nfs_gss_clnt_ctx_unref(struct nfsreq *);
231void	nfs_gss_clnt_ctx_unmount(struct nfsmount *);
232int	nfs_gss_clnt_ctx_remove(struct nfsmount *, kauth_cred_t cred);
233int	nfs_gss_svc_cred_get(struct nfsrv_descript *, struct nfsm_chain *);
234int	nfs_gss_svc_verf_put(struct nfsrv_descript *, struct nfsm_chain *);
235int	nfs_gss_svc_ctx_init(struct nfsrv_descript *, struct nfsrv_sock *, mbuf_t *);
236int	nfs_gss_svc_prepare_reply(struct nfsrv_descript *, struct nfsm_chain *);
237int	nfs_gss_svc_protect_reply(struct nfsrv_descript *, mbuf_t);
238void	nfs_gss_svc_ctx_deref(struct nfs_gss_svc_ctx *);
239void	nfs_gss_svc_cleanup(void);
240
241__END_DECLS
242#endif /* _NFS_NFS_GSS_H_ */
243