OSDN Git Service

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