Bug Summary

File:src/lib/libcrypto/x509/by_dir.c
Warning:line 275, column 14
Value stored to 'postfix' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name by_dir.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libcrypto/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -D HAVE_FUNOPEN -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/arch/amd64 -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bn/arch/amd64 -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/curve25519 -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hidden -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/kdf -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/pkcs12 -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/sha -I /usr/src/lib/libcrypto/ts -I /usr/src/lib/libcrypto/x509 -I /usr/src/lib/libcrypto/obj -D AES_ASM -D BSAES_ASM -D VPAES_ASM -D OPENSSL_IA32_SSE2 -D RSA_ASM -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D MD5_ASM -D GHASH_ASM -D RC4_MD5_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D WHIRLPOOL_ASM -D OPENSSL_CPUID_OBJ -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libcrypto/x509/by_dir.c
1/* $OpenBSD: by_dir.c,v 1.46 2023/12/29 05:33:32 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <sys/stat.h>
60#include <sys/types.h>
61
62#include <errno(*__errno()).h>
63#include <stdio.h>
64#include <string.h>
65#include <time.h>
66#include <unistd.h>
67
68#include <openssl/opensslconf.h>
69
70#include <openssl/err.h>
71#include <openssl/x509.h>
72
73#include "x509_local.h"
74
75typedef struct lookup_dir_hashes_st {
76 unsigned long hash;
77 int suffix;
78} BY_DIR_HASH;
79
80typedef struct lookup_dir_entry_st {
81 char *dir;
82 int dir_type;
83 STACK_OF(BY_DIR_HASH)struct stack_st_BY_DIR_HASH *hashes;
84} BY_DIR_ENTRY;
85
86typedef struct lookup_dir_st {
87 BUF_MEM *buffer;
88 STACK_OF(BY_DIR_ENTRY)struct stack_st_BY_DIR_ENTRY *dirs;
89} BY_DIR;
90
91DECLARE_STACK_OF(BY_DIR_HASH)struct stack_st_BY_DIR_HASH { _STACK stack; };
92DECLARE_STACK_OF(BY_DIR_ENTRY)struct stack_st_BY_DIR_ENTRY { _STACK stack; };
93
94static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
95 char **ret);
96static int new_dir(X509_LOOKUP *lu);
97static void free_dir(X509_LOOKUP *lu);
98static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
99static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
100 X509_OBJECT *ret);
101
102static X509_LOOKUP_METHOD x509_dir_lookup = {
103 .name = "Load certs from files in a directory",
104 .new_item = new_dir,
105 .free = free_dir,
106 .ctrl = dir_ctrl,
107 .get_by_subject = get_cert_by_subject,
108};
109
110X509_LOOKUP_METHOD *
111X509_LOOKUP_hash_dir(void)
112{
113 return &x509_dir_lookup;
114}
115LCRYPTO_ALIAS(X509_LOOKUP_hash_dir)asm("");
116
117static int
118dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
119 char **retp)
120{
121 BY_DIR *ld = ctx->method_data;
122 int ret = 0;
123
124 switch (cmd) {
125 case X509_L_ADD_DIR2:
126 if (argl == X509_FILETYPE_DEFAULT3) {
127 ret = add_cert_dir(ld, X509_get_default_cert_dir(),
128 X509_FILETYPE_PEM1);
129 if (!ret) {
130 X509error(X509_R_LOADING_CERT_DIR)ERR_put_error(11,(0xfff),(103),"/usr/src/lib/libcrypto/x509/by_dir.c"
,130)
;
131 }
132 } else
133 ret = add_cert_dir(ld, argp, (int)argl);
134 break;
135 }
136 return ret;
137}
138
139static int
140new_dir(X509_LOOKUP *lu)
141{
142 BY_DIR *a;
143
144 if ((a = malloc(sizeof(*a))) == NULL((void *)0)) {
145 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,145)
;
146 return 0;
147 }
148 if ((a->buffer = BUF_MEM_new()) == NULL((void *)0)) {
149 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,149)
;
150 free(a);
151 return 0;
152 }
153 a->dirs = NULL((void *)0);
154 lu->method_data = a;
155 return 1;
156}
157
158static void
159by_dir_hash_free(BY_DIR_HASH *hash)
160{
161 free(hash);
162}
163
164static int
165by_dir_hash_cmp(const BY_DIR_HASH * const *a,
166 const BY_DIR_HASH * const *b)
167{
168 if ((*a)->hash > (*b)->hash)
169 return 1;
170 if ((*a)->hash < (*b)->hash)
171 return -1;
172 return 0;
173}
174
175static void
176by_dir_entry_free(BY_DIR_ENTRY *ent)
177{
178 free(ent->dir);
179 sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free)sk_pop_free(((_STACK*) (1 ? (ent->hashes) : (struct stack_st_BY_DIR_HASH
*)0)), ((void (*)(void *)) ((1 ? (by_dir_hash_free) : (void (
*)(BY_DIR_HASH *))0))))
;
180 free(ent);
181}
182
183static void
184free_dir(X509_LOOKUP *lu)
185{
186 BY_DIR *a;
187
188 a = lu->method_data;
189 sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free)sk_pop_free(((_STACK*) (1 ? (a->dirs) : (struct stack_st_BY_DIR_ENTRY
*)0)), ((void (*)(void *)) ((1 ? (by_dir_entry_free) : (void (
*)(BY_DIR_ENTRY *))0))))
;
190 BUF_MEM_free(a->buffer);
191 free(a);
192}
193
194static int
195add_cert_dir(BY_DIR *ctx, const char *dir, int type)
196{
197 int j;
198 const char *s, *ss, *p;
199 ptrdiff_t len;
200
201 if (dir == NULL((void *)0) || !*dir) {
202 X509error(X509_R_INVALID_DIRECTORY)ERR_put_error(11,(0xfff),(113),"/usr/src/lib/libcrypto/x509/by_dir.c"
,202)
;
203 return 0;
204 }
205
206 s = dir;
207 p = s;
208 do {
209 if ((*p == ':') || (*p == '\0')) {
210 BY_DIR_ENTRY *ent;
211
212 ss = s;
213 s = p + 1;
214 len = p - ss;
215 if (len == 0)
216 continue;
217 for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs)sk_num(((_STACK*) (1 ? (ctx->dirs) : (struct stack_st_BY_DIR_ENTRY
*)0)))
; j++) {
218 ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j)((BY_DIR_ENTRY *)sk_value(((_STACK*) (1 ? (ctx->dirs) : (struct
stack_st_BY_DIR_ENTRY*)0)), (j)))
;
219 if (strlen(ent->dir) == (size_t)len &&
220 strncmp(ent->dir, ss, (size_t)len) == 0)
221 break;
222 }
223 if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)sk_num(((_STACK*) (1 ? (ctx->dirs) : (struct stack_st_BY_DIR_ENTRY
*)0)))
)
224 continue;
225 if (ctx->dirs == NULL((void *)0)) {
226 ctx->dirs = sk_BY_DIR_ENTRY_new_null()((struct stack_st_BY_DIR_ENTRY *)sk_new_null());
227 if (ctx->dirs == NULL((void *)0)) {
228 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,228)
;
229 return 0;
230 }
231 }
232 ent = malloc(sizeof(*ent));
233 if (ent == NULL((void *)0)) {
234 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,234)
;
235 return 0;
236 }
237 ent->dir_type = type;
238 ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp)((struct stack_st_BY_DIR_HASH *)sk_new(((int (*)(const void *
, const void *)) ((1 ? (by_dir_hash_cmp) : (int (*)(const BY_DIR_HASH
* const *, const BY_DIR_HASH * const *))0)))))
;
239 ent->dir = strndup(ss, (size_t)len);
240 if (ent->dir == NULL((void *)0) || ent->hashes == NULL((void *)0)) {
241 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,241)
;
242 by_dir_entry_free(ent);
243 return 0;
244 }
245 if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)sk_push(((_STACK*) (1 ? (ctx->dirs) : (struct stack_st_BY_DIR_ENTRY
*)0)), ((void*) (1 ? (ent) : (BY_DIR_ENTRY*)0)))
) {
246 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,246)
;
247 by_dir_entry_free(ent);
248 return 0;
249 }
250 }
251 } while (*p++ != '\0');
252 return 1;
253}
254
255static int
256get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
257 X509_OBJECT *ret)
258{
259 BY_DIR *ctx;
260 union {
261 struct {
262 X509 st_x509;
263 X509_CINF st_x509_cinf;
264 } x509;
265 struct {
266 X509_CRL st_crl;
267 X509_CRL_INFO st_crl_info;
268 } crl;
269 } data;
270 int ok = 0;
271 int i, j, k;
272 unsigned long h;
273 BUF_MEM *b = NULL((void *)0);
274 X509_OBJECT stmp, *tmp;
275 const char *postfix="";
Value stored to 'postfix' during its initialization is never read
276
277 if (name == NULL((void *)0))
278 return 0;
279
280 stmp.type = type;
281 if (type == X509_LU_X509) {
282 data.x509.st_x509.cert_info = &data.x509.st_x509_cinf;
283 data.x509.st_x509_cinf.subject = name;
284 stmp.data.x509 = &data.x509.st_x509;
285 postfix="";
286 } else if (type == X509_LU_CRL) {
287 data.crl.st_crl.crl = &data.crl.st_crl_info;
288 data.crl.st_crl_info.issuer = name;
289 stmp.data.crl = &data.crl.st_crl;
290 postfix="r";
291 } else {
292 X509error(X509_R_WRONG_LOOKUP_TYPE)ERR_put_error(11,(0xfff),(112),"/usr/src/lib/libcrypto/x509/by_dir.c"
,292)
;
293 goto finish;
294 }
295
296 if ((b = BUF_MEM_new()) == NULL((void *)0)) {
297 X509error(ERR_R_BUF_LIB)ERR_put_error(11,(0xfff),(7),"/usr/src/lib/libcrypto/x509/by_dir.c"
,297)
;
298 goto finish;
299 }
300
301 ctx = xl->method_data;
302
303 h = X509_NAME_hash(name);
304 for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs)sk_num(((_STACK*) (1 ? (ctx->dirs) : (struct stack_st_BY_DIR_ENTRY
*)0)))
; i++) {
305 BY_DIR_ENTRY *ent;
306 int idx;
307 BY_DIR_HASH htmp, *hent;
308
309 ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i)((BY_DIR_ENTRY *)sk_value(((_STACK*) (1 ? (ctx->dirs) : (struct
stack_st_BY_DIR_ENTRY*)0)), (i)))
;
310 j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
311 if (!BUF_MEM_grow(b, j)) {
312 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,312)
;
313 goto finish;
314 }
315 if (type == X509_LU_CRL) {
316 htmp.hash = h;
317 CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(1|4,11,((void *)0),0);
318 idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp)sk_find(((_STACK*) (1 ? (ent->hashes) : (struct stack_st_BY_DIR_HASH
*)0)), ((void*) (1 ? (&htmp) : (BY_DIR_HASH*)0)))
;
319 if (idx >= 0) {
320 hent = sk_BY_DIR_HASH_value(ent->hashes, idx)((BY_DIR_HASH *)sk_value(((_STACK*) (1 ? (ent->hashes) : (
struct stack_st_BY_DIR_HASH*)0)), (idx)))
;
321 k = hent->suffix;
322 } else {
323 hent = NULL((void *)0);
324 k = 0;
325 }
326 CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(2|4,11,((void *)0),0);
327 } else {
328 k = 0;
329 hent = NULL((void *)0);
330 }
331 for (;;) {
332 (void) snprintf(b->data, b->max, "%s/%08lx.%s%d",
333 ent->dir, h, postfix, k);
334
335 {
336 struct stat st;
337 if (stat(b->data, &st) < 0)
338 break;
339 }
340 /* found one. */
341 if (type == X509_LU_X509) {
342 if ((X509_load_cert_file(xl, b->data,
343 ent->dir_type)) == 0)
344 break;
345 } else if (type == X509_LU_CRL) {
346 if ((X509_load_crl_file(xl, b->data,
347 ent->dir_type)) == 0)
348 break;
349 }
350 /* else case will caught higher up */
351 k++;
352 }
353
354 /* we have added it to the cache so now pull it out again */
355 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(1|8,11,((void *)0),0);
356 j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp)sk_find(((_STACK*) (1 ? (xl->store_ctx->objs) : (struct
stack_st_X509_OBJECT*)0)), ((void*) (1 ? (&stmp) : (X509_OBJECT
*)0)))
;
357 tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j)((X509_OBJECT *)sk_value(((_STACK*) (1 ? (xl->store_ctx->
objs) : (struct stack_st_X509_OBJECT*)0)), (j)))
;
358 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(2|8,11,((void *)0),0);
359
360 /* If a CRL, update the last file suffix added for this */
361 if (type == X509_LU_CRL) {
362 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(1|8,11,((void *)0),0);
363 /*
364 * Look for entry again in case another thread added
365 * an entry first.
366 */
367 if (hent == NULL((void *)0)) {
368 htmp.hash = h;
369 idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp)sk_find(((_STACK*) (1 ? (ent->hashes) : (struct stack_st_BY_DIR_HASH
*)0)), ((void*) (1 ? (&htmp) : (BY_DIR_HASH*)0)))
;
370 hent = sk_BY_DIR_HASH_value(ent->hashes, idx)((BY_DIR_HASH *)sk_value(((_STACK*) (1 ? (ent->hashes) : (
struct stack_st_BY_DIR_HASH*)0)), (idx)))
;
371 }
372 if (hent == NULL((void *)0)) {
373 hent = malloc(sizeof(*hent));
374 if (hent == NULL((void *)0)) {
375 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,375)
;
376 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(2|8,11,((void *)0),0);
377 ok = 0;
378 goto finish;
379 }
380 hent->hash = h;
381 hent->suffix = k;
382 if (!sk_BY_DIR_HASH_push(ent->hashes, hent)sk_push(((_STACK*) (1 ? (ent->hashes) : (struct stack_st_BY_DIR_HASH
*)0)), ((void*) (1 ? (hent) : (BY_DIR_HASH*)0)))
) {
383 X509error(ERR_R_MALLOC_FAILURE)ERR_put_error(11,(0xfff),((1|64)),"/usr/src/lib/libcrypto/x509/by_dir.c"
,383)
;
384 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(2|8,11,((void *)0),0);
385 free(hent);
386 ok = 0;
387 goto finish;
388 }
389 } else if (hent->suffix < k)
390 hent->suffix = k;
391
392 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE)CRYPTO_lock(2|8,11,((void *)0),0);
393
394 }
395
396 if (tmp != NULL((void *)0)) {
397 ok = 1;
398 ret->type = tmp->type;
399 memcpy(&ret->data, &tmp->data, sizeof(ret->data));
400 goto finish;
401 }
402 }
403finish:
404 BUF_MEM_free(b);
405 return ok;
406}