]>
Commit | Line | Data |
---|---|---|
1c1af145 | 1 | #include "putty.h" |
2 | ||
3 | #include <string.h> | |
4 | #include "sshgssc.h" | |
5 | #include "misc.h" | |
6 | ||
7 | #ifndef NO_GSSAPI | |
8 | ||
9 | static Ssh_gss_stat ssh_gssapi_indicate_mech(struct ssh_gss_library *lib, | |
10 | Ssh_gss_buf *mech) | |
11 | { | |
12 | /* Copy constant into mech */ | |
13 | mech->length = GSS_MECH_KRB5->length; | |
14 | mech->value = GSS_MECH_KRB5->elements; | |
15 | return SSH_GSS_OK; | |
16 | } | |
17 | ||
18 | static Ssh_gss_stat ssh_gssapi_import_name(struct ssh_gss_library *lib, | |
19 | char *host, | |
20 | Ssh_gss_name *srv_name) | |
21 | { | |
22 | struct gssapi_functions *gss = &lib->u.gssapi; | |
23 | OM_uint32 min_stat,maj_stat; | |
24 | gss_buffer_desc host_buf; | |
25 | char *pStr; | |
26 | ||
27 | pStr = dupcat("host@", host, NULL); | |
28 | ||
29 | host_buf.value = pStr; | |
30 | host_buf.length = strlen(pStr); | |
31 | ||
32 | maj_stat = gss->import_name(&min_stat, &host_buf, | |
33 | GSS_C_NT_HOSTBASED_SERVICE, srv_name); | |
34 | /* Release buffer */ | |
35 | sfree(pStr); | |
36 | if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK; | |
37 | return SSH_GSS_FAILURE; | |
38 | } | |
39 | ||
40 | static Ssh_gss_stat ssh_gssapi_acquire_cred(struct ssh_gss_library *lib, | |
41 | Ssh_gss_ctx *ctx) | |
42 | { | |
43 | gssapi_ssh_gss_ctx *gssctx = snew(gssapi_ssh_gss_ctx); | |
44 | ||
45 | gssctx->maj_stat = gssctx->min_stat = GSS_S_COMPLETE; | |
46 | gssctx->ctx = GSS_C_NO_CONTEXT; | |
47 | *ctx = (Ssh_gss_ctx) gssctx; | |
48 | ||
49 | return SSH_GSS_OK; | |
50 | } | |
51 | ||
52 | static Ssh_gss_stat ssh_gssapi_init_sec_context(struct ssh_gss_library *lib, | |
53 | Ssh_gss_ctx *ctx, | |
54 | Ssh_gss_name srv_name, | |
55 | int to_deleg, | |
56 | Ssh_gss_buf *recv_tok, | |
57 | Ssh_gss_buf *send_tok) | |
58 | { | |
59 | struct gssapi_functions *gss = &lib->u.gssapi; | |
60 | gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx*) *ctx; | |
61 | OM_uint32 ret_flags; | |
62 | ||
63 | if (to_deleg) to_deleg = GSS_C_DELEG_FLAG; | |
64 | gssctx->maj_stat = gss->init_sec_context(&gssctx->min_stat, | |
65 | GSS_C_NO_CREDENTIAL, | |
66 | &gssctx->ctx, | |
67 | srv_name, | |
68 | (gss_OID) GSS_MECH_KRB5, | |
69 | GSS_C_MUTUAL_FLAG | | |
70 | GSS_C_INTEG_FLAG | to_deleg, | |
71 | 0, | |
72 | GSS_C_NO_CHANNEL_BINDINGS, | |
73 | recv_tok, | |
74 | NULL, /* ignore mech type */ | |
75 | send_tok, | |
76 | &ret_flags, | |
77 | NULL); /* ignore time_rec */ | |
78 | ||
79 | if (gssctx->maj_stat == GSS_S_COMPLETE) return SSH_GSS_S_COMPLETE; | |
80 | if (gssctx->maj_stat == GSS_S_CONTINUE_NEEDED) return SSH_GSS_S_CONTINUE_NEEDED; | |
81 | return SSH_GSS_FAILURE; | |
82 | } | |
83 | ||
84 | static Ssh_gss_stat ssh_gssapi_display_status(struct ssh_gss_library *lib, | |
85 | Ssh_gss_ctx ctx, | |
86 | Ssh_gss_buf *buf) | |
87 | { | |
88 | struct gssapi_functions *gss = &lib->u.gssapi; | |
89 | gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx *) ctx; | |
90 | OM_uint32 lmin,lmax; | |
91 | OM_uint32 ccc; | |
92 | gss_buffer_desc msg_maj=GSS_C_EMPTY_BUFFER; | |
93 | gss_buffer_desc msg_min=GSS_C_EMPTY_BUFFER; | |
94 | ||
95 | /* Return empty buffer in case of failure */ | |
96 | SSH_GSS_CLEAR_BUF(buf); | |
97 | ||
98 | /* get first mesg from GSS */ | |
99 | ccc=0; | |
100 | lmax=gss->display_status(&lmin,gssctx->maj_stat,GSS_C_GSS_CODE,(gss_OID) GSS_MECH_KRB5,&ccc,&msg_maj); | |
101 | ||
102 | if (lmax != GSS_S_COMPLETE) return SSH_GSS_FAILURE; | |
103 | ||
104 | /* get first mesg from Kerberos */ | |
105 | ccc=0; | |
106 | lmax=gss->display_status(&lmin,gssctx->min_stat,GSS_C_MECH_CODE,(gss_OID) GSS_MECH_KRB5,&ccc,&msg_min); | |
107 | ||
108 | if (lmax != GSS_S_COMPLETE) { | |
109 | gss->release_buffer(&lmin, &msg_maj); | |
110 | return SSH_GSS_FAILURE; | |
111 | } | |
112 | ||
113 | /* copy data into buffer */ | |
114 | buf->length = msg_maj.length + msg_min.length + 1; | |
115 | buf->value = snewn(buf->length + 1, char); | |
116 | ||
117 | /* copy mem */ | |
118 | memcpy((char *)buf->value, msg_maj.value, msg_maj.length); | |
119 | ((char *)buf->value)[msg_maj.length] = ' '; | |
120 | memcpy((char *)buf->value + msg_maj.length + 1, msg_min.value, msg_min.length); | |
121 | ((char *)buf->value)[buf->length] = 0; | |
122 | /* free mem & exit */ | |
123 | gss->release_buffer(&lmin, &msg_maj); | |
124 | gss->release_buffer(&lmin, &msg_min); | |
125 | return SSH_GSS_OK; | |
126 | } | |
127 | ||
128 | static Ssh_gss_stat ssh_gssapi_free_tok(struct ssh_gss_library *lib, | |
129 | Ssh_gss_buf *send_tok) | |
130 | { | |
131 | struct gssapi_functions *gss = &lib->u.gssapi; | |
132 | OM_uint32 min_stat,maj_stat; | |
133 | maj_stat = gss->release_buffer(&min_stat, send_tok); | |
134 | ||
135 | if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK; | |
136 | return SSH_GSS_FAILURE; | |
137 | } | |
138 | ||
139 | static Ssh_gss_stat ssh_gssapi_release_cred(struct ssh_gss_library *lib, | |
140 | Ssh_gss_ctx *ctx) | |
141 | { | |
142 | struct gssapi_functions *gss = &lib->u.gssapi; | |
143 | gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx *) *ctx; | |
144 | OM_uint32 min_stat; | |
145 | OM_uint32 maj_stat=GSS_S_COMPLETE; | |
146 | ||
147 | if (gssctx == NULL) return SSH_GSS_FAILURE; | |
148 | if (gssctx->ctx != GSS_C_NO_CONTEXT) | |
149 | maj_stat = gss->delete_sec_context(&min_stat,&gssctx->ctx,GSS_C_NO_BUFFER); | |
150 | sfree(gssctx); | |
151 | ||
152 | if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK; | |
153 | return SSH_GSS_FAILURE; | |
154 | } | |
155 | ||
156 | ||
157 | static Ssh_gss_stat ssh_gssapi_release_name(struct ssh_gss_library *lib, | |
158 | Ssh_gss_name *srv_name) | |
159 | { | |
160 | struct gssapi_functions *gss = &lib->u.gssapi; | |
161 | OM_uint32 min_stat,maj_stat; | |
162 | maj_stat = gss->release_name(&min_stat, srv_name); | |
163 | ||
164 | if (maj_stat == GSS_S_COMPLETE) return SSH_GSS_OK; | |
165 | return SSH_GSS_FAILURE; | |
166 | } | |
167 | ||
168 | static Ssh_gss_stat ssh_gssapi_get_mic(struct ssh_gss_library *lib, | |
169 | Ssh_gss_ctx ctx, Ssh_gss_buf *buf, | |
170 | Ssh_gss_buf *hash) | |
171 | { | |
172 | struct gssapi_functions *gss = &lib->u.gssapi; | |
173 | gssapi_ssh_gss_ctx *gssctx = (gssapi_ssh_gss_ctx *) ctx; | |
174 | if (gssctx == NULL) return SSH_GSS_FAILURE; | |
175 | return gss->get_mic(&(gssctx->min_stat), gssctx->ctx, 0, buf, hash); | |
176 | } | |
177 | ||
178 | static Ssh_gss_stat ssh_gssapi_free_mic(struct ssh_gss_library *lib, | |
179 | Ssh_gss_buf *hash) | |
180 | { | |
181 | /* On Unix this is the same freeing process as ssh_gssapi_free_tok. */ | |
182 | return ssh_gssapi_free_tok(lib, hash); | |
183 | } | |
184 | ||
185 | void ssh_gssapi_bind_fns(struct ssh_gss_library *lib) | |
186 | { | |
187 | lib->indicate_mech = ssh_gssapi_indicate_mech; | |
188 | lib->import_name = ssh_gssapi_import_name; | |
189 | lib->release_name = ssh_gssapi_release_name; | |
190 | lib->init_sec_context = ssh_gssapi_init_sec_context; | |
191 | lib->free_tok = ssh_gssapi_free_tok; | |
192 | lib->acquire_cred = ssh_gssapi_acquire_cred; | |
193 | lib->release_cred = ssh_gssapi_release_cred; | |
194 | lib->get_mic = ssh_gssapi_get_mic; | |
195 | lib->free_mic = ssh_gssapi_free_mic; | |
196 | lib->display_status = ssh_gssapi_display_status; | |
197 | } | |
198 | ||
199 | #else | |
200 | ||
201 | /* Dummy function so this source file defines something if NO_GSSAPI | |
202 | is defined. */ | |
203 | ||
204 | int ssh_gssapi_init(void) | |
205 | { | |
206 | return 0; | |
207 | } | |
208 | ||
209 | #endif |