From cbecb3ac3763f1179dc220a69d28e92f58e9443e Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 15 Jul 2002 15:35:40 +0000 Subject: [PATCH] There's an ongoing project to bring some kind of path selection mechanism to the ENGINE framework. This means there there are going to be new functionality for the DSO part, and ultimately some way of merging two file specifications together. This commit places the merging code into the repository. It's currently not used anywhere, and hasn't been tested at all. It may be full of errors, including syntactical ones. Those will be fixed as promptly as possible. --- crypto/dso/dso.h | 40 +++++- crypto/dso/dso_dl.c | 70 +++++++++- crypto/dso/dso_dlfcn.c | 72 +++++++++- crypto/dso/dso_err.c | 10 +- crypto/dso/dso_lib.c | 29 +++- crypto/dso/dso_vms.c | 128 ++++++++++++++++- crypto/dso/dso_win32.c | 303 ++++++++++++++++++++++++++++++++++++++++- 7 files changed, 644 insertions(+), 8 deletions(-) diff --git a/crypto/dso/dso.h b/crypto/dso/dso.h index aa721f7feb..2cf6e1ae12 100644 --- a/crypto/dso/dso.h +++ b/crypto/dso/dso.h @@ -1,4 +1,4 @@ -/* dso.h */ +/* dso.h -*- mode:C; c-file-style: "eay" -*- */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -107,6 +107,22 @@ typedef struct dso_st DSO; * condition) or a newly allocated string containing the transformed form that * the caller will need to free with OPENSSL_free() when done. */ typedef char* (*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *); +/* The function prototype used for method functions (or caller-provided + * callbacks) that merge two file specifications. They are passed a + * DSO structure pointer (or NULL if they are to be used independantly of + * a DSO object) and two file specifications to merge. They should + * either return NULL (if there is an error condition) or a newly allocated + * string containing the result of merging that the caller will need + * to free with OPENSSL_free() when done. + * Here, merging means that bits and pieces are taken from each of the + * file specifications and added together in whatever fashion that is + * sensible for the DSO method in question. The only rule that really + * applies is that if the two specification contain pieces of the same + * type, the copy from the string string takes priority. One could see + * it as the first specification is the one given by the user and the + * second being a bunch of defaults to add on if they're missing in the + * first. */ +typedef char* (*DSO_MERGER_FUNC)(DSO *, const char *, const char *); typedef struct dso_meth_st { @@ -140,6 +156,9 @@ typedef struct dso_meth_st /* The default DSO_METHOD-specific function for converting filenames to * a canonical native form. */ DSO_NAME_CONVERTER_FUNC dso_name_converter; + /* The default DSO_METHOD-specific function for converting filenames to + * a canonical native form. */ + DSO_MERGER_FUNC dso_merger; /* [De]Initialisation handlers. */ int (*init)(DSO *dso); @@ -164,9 +183,13 @@ struct dso_st * don't touch meth_data! */ CRYPTO_EX_DATA ex_data; /* If this callback function pointer is set to non-NULL, then it will - * be used on DSO_load() in place of meth->dso_name_converter. NB: This + * be used in DSO_load() in place of meth->dso_name_converter. NB: This * should normally set using DSO_set_name_converter(). */ DSO_NAME_CONVERTER_FUNC name_converter; + /* If this callback function pointer is set to non-NULL, then it will + * be used in DSO_load() in place of meth->dso_merger. NB: This + * should normally set using DSO_set_merger(). */ + DSO_MERGER_FUNC merger; /* This is populated with (a copy of) the platform-independant * filename used for this DSO. */ char *filename; @@ -209,6 +232,11 @@ int DSO_set_filename(DSO *dso, const char *filename); * caller-created DSO_METHODs can do the same thing. A non-NULL return value * will need to be OPENSSL_free()'d. */ char *DSO_convert_filename(DSO *dso, const char *filename); +/* This function will invoke the DSO's merger callback to merge two file + * specifications, or if the callback isn't set it will instead use the + * DSO_METHOD's merger. A non-NULL return value will need to be + * OPENSSL_free()'d. */ +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2); /* If the DSO is currently loaded, this returns the filename that it was loaded * under, otherwise it returns NULL. So it is also useful as a test as to * whether the DSO is currently loaded. NB: This will not necessarily return @@ -273,11 +301,13 @@ void ERR_load_DSO_strings(void); #define DSO_F_DLFCN_BIND_FUNC 100 #define DSO_F_DLFCN_BIND_VAR 101 #define DSO_F_DLFCN_LOAD 102 +#define DSO_F_DLFCN_MERGER 130 #define DSO_F_DLFCN_NAME_CONVERTER 123 #define DSO_F_DLFCN_UNLOAD 103 #define DSO_F_DL_BIND_FUNC 104 #define DSO_F_DL_BIND_VAR 105 #define DSO_F_DL_LOAD 106 +#define DSO_F_DL_MERGER 131 #define DSO_F_DL_NAME_CONVERTER 124 #define DSO_F_DL_UNLOAD 107 #define DSO_F_DSO_BIND_FUNC 108 @@ -288,24 +318,30 @@ void ERR_load_DSO_strings(void); #define DSO_F_DSO_GET_FILENAME 127 #define DSO_F_DSO_GET_LOADED_FILENAME 128 #define DSO_F_DSO_LOAD 112 +#define DSO_F_DSO_MERGE 132 #define DSO_F_DSO_NEW_METHOD 113 #define DSO_F_DSO_SET_FILENAME 129 #define DSO_F_DSO_SET_NAME_CONVERTER 122 #define DSO_F_DSO_UP_REF 114 #define DSO_F_VMS_BIND_VAR 115 #define DSO_F_VMS_LOAD 116 +#define DSO_F_VMS_MERGER 133 #define DSO_F_VMS_UNLOAD 117 #define DSO_F_WIN32_BIND_FUNC 118 #define DSO_F_WIN32_BIND_VAR 119 #define DSO_F_WIN32_LOAD 120 +#define DSO_F_WIN32_MERGER 134 #define DSO_F_WIN32_NAME_CONVERTER 125 #define DSO_F_WIN32_UNLOAD 121 /* Reason codes. */ #define DSO_R_CTRL_FAILED 100 #define DSO_R_DSO_ALREADY_LOADED 110 +#define DSO_R_EMPTY_FILE_STRUCTURE 113 +#define DSO_R_FAILURE 114 #define DSO_R_FILENAME_TOO_BIG 101 #define DSO_R_FINISH_FAILED 102 +#define DSO_R_INCORRECT_FILE_SYNTAX 115 #define DSO_R_LOAD_FAILED 103 #define DSO_R_NAME_TRANSLATION_FAILED 109 #define DSO_R_NO_FILENAME 111 diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index 195717e993..32a8d41bf7 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -1,4 +1,4 @@ -/* dso_dl.c */ +/* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL * project 2000. */ @@ -84,6 +84,7 @@ static int dl_finish(DSO *dso); static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg); #endif static char *dl_name_converter(DSO *dso, const char *filename); +static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2); static DSO_METHOD dso_meth_dl = { "OpenSSL 'dl' shared library method", @@ -98,6 +99,7 @@ static DSO_METHOD dso_meth_dl = { #endif NULL, /* ctrl */ dl_name_converter, + dl_merger, NULL, /* init */ NULL /* finish */ }; @@ -238,6 +240,72 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname) return((DSO_FUNC_TYPE)sym); } +static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2) + { + char *merged; + + if(!filespec1 && !filespec2) + { + DSOerr(DSO_F_DL_MERGER, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + /* If the first file specification is a rooted path, it rules. + same goes if the second file specification is missing. */ + if (!filespec2 || filespec1[0] == '/') + { + merged = OPENSSL_malloc(strlen(filespec1) + 1); + if(!merged) + { + DSOerr(DSO_F_DL_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec1); + } + /* If the first file specification is missing, the second one rules. */ + else if (!filespec1) + { + merged = OPENSSL_malloc(strlen(filespec2) + 1); + if(!merged) + { + DSOerr(DSO_F_DL_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + } + else + /* This part isn't as trivial as it looks. It assumes that + the second file specification really is a directory, and + makes no checks whatsoever. Therefore, the result becomes + the concatenation of filespec2 followed by a slash followed + by filespec1. */ + { + int spec2len, len; + + spec2len = (filespec2 ? strlen(filespec2) : 0); + len = spec2len + (filespec1 ? strlen(filespec1) : 0); + + if(filespec2 && filespec2[spec2len - 1] == '/') + { + spec2len--; + len--; + } + merged = OPENSSL_malloc(len + 2); + if(!merged) + { + DSOerr(DSO_F_DL_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + merged[spec2len] = '/'; + strcpy(&merged[spec2len + 1], filespec1); + } + return(merged); + } + /* This function is identical to the one in dso_dlfcn.c, but as it is highly * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at the * same time, there's no great duplicating the code. Figuring out an elegant diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index 906b4703de..de88b2fd16 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -1,4 +1,4 @@ -/* dso_dlfcn.c */ +/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -85,6 +85,8 @@ static int dlfcn_finish(DSO *dso); static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg); #endif static char *dlfcn_name_converter(DSO *dso, const char *filename); +static char *dlfcn_merger(DSO *dso, const char *filespec1, + const char *filespec2); static DSO_METHOD dso_meth_dlfcn = { "OpenSSL 'dlfcn' shared library method", @@ -99,6 +101,7 @@ static DSO_METHOD dso_meth_dlfcn = { #endif NULL, /* ctrl */ dlfcn_name_converter, + dlfcn_merger, NULL, /* init */ NULL /* finish */ }; @@ -252,6 +255,73 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname) return(sym); } +static char *dlfcn_merger(DSO *dso, const char *filespec1, + const char *filespec2) + { + char *merged; + + if(!filespec1 && !filespec2) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + /* If the first file specification is a rooted path, it rules. + same goes if the second file specification is missing. */ + if (!filespec2 || filespec1[0] == '/') + { + merged = OPENSSL_malloc(strlen(filespec1) + 1); + if(!merged) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec1); + } + /* If the first file specification is missing, the second one rules. */ + else if (!filespec1) + { + merged = OPENSSL_malloc(strlen(filespec2) + 1); + if(!merged) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + } + else + /* This part isn't as trivial as it looks. It assumes that + the second file specification really is a directory, and + makes no checks whatsoever. Therefore, the result becomes + the concatenation of filespec2 followed by a slash followed + by filespec1. */ + { + int spec2len, len; + + spec2len = (filespec2 ? strlen(filespec2) : 0); + len = spec2len + (filespec1 ? strlen(filespec1) : 0); + + if(filespec2 && filespec2[spec2len - 1] == '/') + { + spec2len--; + len--; + } + merged = OPENSSL_malloc(len + 2); + if(!merged) + { + DSOerr(DSO_F_DLFCN_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + merged[spec2len] = '/'; + strcpy(&merged[spec2len + 1], filespec1); + } + return(merged); + } + static char *dlfcn_name_converter(DSO *dso, const char *filename) { char *translated; diff --git a/crypto/dso/dso_err.c b/crypto/dso/dso_err.c index cf452de1aa..23ccfc00c5 100644 --- a/crypto/dso/dso_err.c +++ b/crypto/dso/dso_err.c @@ -1,6 +1,6 @@ /* crypto/dso/dso_err.c */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -69,11 +69,13 @@ static ERR_STRING_DATA DSO_str_functs[]= {ERR_PACK(0,DSO_F_DLFCN_BIND_FUNC,0), "DLFCN_BIND_FUNC"}, {ERR_PACK(0,DSO_F_DLFCN_BIND_VAR,0), "DLFCN_BIND_VAR"}, {ERR_PACK(0,DSO_F_DLFCN_LOAD,0), "DLFCN_LOAD"}, +{ERR_PACK(0,DSO_F_DLFCN_MERGER,0), "DLFCN_MERGER"}, {ERR_PACK(0,DSO_F_DLFCN_NAME_CONVERTER,0), "DLFCN_NAME_CONVERTER"}, {ERR_PACK(0,DSO_F_DLFCN_UNLOAD,0), "DLFCN_UNLOAD"}, {ERR_PACK(0,DSO_F_DL_BIND_FUNC,0), "DL_BIND_FUNC"}, {ERR_PACK(0,DSO_F_DL_BIND_VAR,0), "DL_BIND_VAR"}, {ERR_PACK(0,DSO_F_DL_LOAD,0), "DL_LOAD"}, +{ERR_PACK(0,DSO_F_DL_MERGER,0), "DL_MERGER"}, {ERR_PACK(0,DSO_F_DL_NAME_CONVERTER,0), "DL_NAME_CONVERTER"}, {ERR_PACK(0,DSO_F_DL_UNLOAD,0), "DL_UNLOAD"}, {ERR_PACK(0,DSO_F_DSO_BIND_FUNC,0), "DSO_bind_func"}, @@ -84,16 +86,19 @@ static ERR_STRING_DATA DSO_str_functs[]= {ERR_PACK(0,DSO_F_DSO_GET_FILENAME,0), "DSO_get_filename"}, {ERR_PACK(0,DSO_F_DSO_GET_LOADED_FILENAME,0), "DSO_get_loaded_filename"}, {ERR_PACK(0,DSO_F_DSO_LOAD,0), "DSO_load"}, +{ERR_PACK(0,DSO_F_DSO_MERGE,0), "DSO_merge"}, {ERR_PACK(0,DSO_F_DSO_NEW_METHOD,0), "DSO_new_method"}, {ERR_PACK(0,DSO_F_DSO_SET_FILENAME,0), "DSO_set_filename"}, {ERR_PACK(0,DSO_F_DSO_SET_NAME_CONVERTER,0), "DSO_set_name_converter"}, {ERR_PACK(0,DSO_F_DSO_UP_REF,0), "DSO_up_ref"}, {ERR_PACK(0,DSO_F_VMS_BIND_VAR,0), "VMS_BIND_VAR"}, {ERR_PACK(0,DSO_F_VMS_LOAD,0), "VMS_LOAD"}, +{ERR_PACK(0,DSO_F_VMS_MERGER,0), "VMS_MERGER"}, {ERR_PACK(0,DSO_F_VMS_UNLOAD,0), "VMS_UNLOAD"}, {ERR_PACK(0,DSO_F_WIN32_BIND_FUNC,0), "WIN32_BIND_FUNC"}, {ERR_PACK(0,DSO_F_WIN32_BIND_VAR,0), "WIN32_BIND_VAR"}, {ERR_PACK(0,DSO_F_WIN32_LOAD,0), "WIN32_LOAD"}, +{ERR_PACK(0,DSO_F_WIN32_MERGER,0), "WIN32_MERGER"}, {ERR_PACK(0,DSO_F_WIN32_NAME_CONVERTER,0), "WIN32_NAME_CONVERTER"}, {ERR_PACK(0,DSO_F_WIN32_UNLOAD,0), "WIN32_UNLOAD"}, {0,NULL} @@ -103,8 +108,11 @@ static ERR_STRING_DATA DSO_str_reasons[]= { {DSO_R_CTRL_FAILED ,"control command failed"}, {DSO_R_DSO_ALREADY_LOADED ,"dso already loaded"}, +{DSO_R_EMPTY_FILE_STRUCTURE ,"empty file structure"}, +{DSO_R_FAILURE ,"failure"}, {DSO_R_FILENAME_TOO_BIG ,"filename too big"}, {DSO_R_FINISH_FAILED ,"cleanup method function failed"}, +{DSO_R_INCORRECT_FILE_SYNTAX ,"incorrect file syntax"}, {DSO_R_LOAD_FAILED ,"could not load the shared library"}, {DSO_R_NAME_TRANSLATION_FAILED ,"name translation failed"}, {DSO_R_NO_FILENAME ,"no filename"}, diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 556069b9b8..e7ddfd5ecf 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -1,4 +1,4 @@ -/* dso_lib.c */ +/* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -390,6 +390,33 @@ int DSO_set_filename(DSO *dso, const char *filename) return(1); } +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2) + { + char *result = NULL; + + if(dso == NULL || dir == NULL) + { + DSOerr(DSO_F_DSO_MERGE,ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(filespec1 == NULL) + filespec1 = dso->filename; + if(filespec1 == NULL) + { + DSOerr(DSO_F_DSO_MERGE,DSO_R_NO_FILENAME); + return(NULL); + } + if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) + { + if(dso->merger != NULL) + result = dso->merger(dso, filespec1, filespec2); + else if(dso->meth->dso_merger != NULL) + result = dso->meth->dso_merger(dso, + filespec1, filespec2); + } + return(result); + } + char *DSO_convert_filename(DSO *dso, const char *filename) { char *result = NULL; diff --git a/crypto/dso/dso_vms.c b/crypto/dso/dso_vms.c index 1674619d17..696e1cc84b 100644 --- a/crypto/dso/dso_vms.c +++ b/crypto/dso/dso_vms.c @@ -1,4 +1,4 @@ -/* dso_vms.c */ +/* dso_vms.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL * project 2000. */ @@ -63,6 +63,7 @@ #include #ifdef OPENSSL_SYS_VMS #pragma message disable DOLLARID +#include #include #include #include @@ -89,6 +90,8 @@ static int vms_finish(DSO *dso); static long vms_ctrl(DSO *dso, int cmd, long larg, void *parg); #endif static char *vms_name_converter(DSO *dso, const char *filename); +static char *vms_merger(DSO *dso, const char *filespec1, + const char *filespec2); static DSO_METHOD dso_meth_vms = { "OpenSSL 'VMS' shared library method", @@ -103,6 +106,7 @@ static DSO_METHOD dso_meth_vms = { #endif NULL, /* ctrl */ vms_name_converter, + vms_merger, NULL, /* init */ NULL /* finish */ }; @@ -368,6 +372,128 @@ static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname) return sym; } +static char *vms_merger(DSO *dso, const char *filespec1, const char *filespec2) + { + int status; + int filespec1len, filespec2len; + struct FAB fab; +#ifdef NAML$C_MAXRSS + struct NAML nam; + char esa[NAML$C_MAXRSS]; +#else + struct NAM nam; + char esa[NAM$C_MAXRSS]; +#endif + char *merged; + + if (!filespec1) filespec1 = ""; + if (!filespec2) filespec2 = ""; + filespec1len = strlen(filespec1); + filespec2len = strlen(filespec2); + + fab = cc$rms_fab; +#ifdef NAML$C_MAXRSS + nam = cc$rms_naml; +#else + nam = cc$rms_nam; +#endif + + fab.fab$l_fna = filespec1; + fab.fab$b_fns = filespec1len; + fab.fab$l_dna = filespec2; + fab.fab$b_dns = filespec2len; +#ifdef NAML$C_MAXRSS + if (filespec1len > NAM$C_MAXRSS) + { + fab.fab$l_fna = -1; + fab.fab$b_fns = 0; + nam.naml$l_long_filename = filespec1; + nam.naml$l_long_filename_size = filespec1len; + } + if (filespec2len > NAM$C_MAXRSS) + { + fab.fab$l_dna = -1; + fab.fab$b_dns = 0; + nam.naml$l_long_defname = filespec2; + nam.naml$l_long_defname_size = filespec2len; + } + nam.naml$l_esa = esa; + nam.naml$b_ess = NAM$C_MAXRSS; + nam.naml$l_long_expand = esa; + nam.naml$l_long_expand_alloc = sizeof(esa); + nam.naml$b_nop = NAM$M_SYNCHK | NAM$M_PWD; + nam.naml$v_no_short_updase = 1; +#else + nam.nam$l_esa = esa; + nam.nam$b_ess = NAM$C_MAXRSS; + nam.nam$b_nop = NAM$M_SYNCHK | NAM$M_PWD; +#endif + fab.fab$l_nam = &nam; + + status = sys$parse(&fab, 0, 0); + + if(!$VMS_STATUS_SUCCESS(status)) + { + unsigned short length; + char errstring[257]; + struct dsc$descriptor_s errstring_dsc; + + errstring_dsc.dsc$w_length = sizeof(errstring); + errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T; + errstring_dsc.dsc$b_class = DSC$K_CLASS_S; + errstring_dsc.dsc$a_pointer = errstring; + + *sym = NULL; + + status = sys$getmsg(status, &length, &errstring_dsc, 1, 0); + + if (!$VMS_STATUS_SUCCESS(status)) + lib$signal(status); /* This is really bad. Abort! */ + else + { + errstring[length] = '\0'; + + DSOerr(DSO_F_VMS_MERGER,DSO_R_FAILURE); + ERR_add_error_data(9, + "filespec \"", filespec1, "\", ", + "defaults \"", filespec2, "\": " + errstring); + } + return(NULL); + } +#ifdef NAML$C_MAXRSS + if (nam.naml$l_long_expand_size) + { + merged = OPENSSL_malloc(nam.naml$l_long_expand_size + 1); + if(!merged) + goto malloc_err; + strncpy(merged, nam.naml$l_long_expand, + nam.naml$l_long_expand_size); + merged[nam.naml$l_long_expand_size] = '\0'; + } + else + { + merged = OPENSSL_malloc(nam.naml$l_esl + 1); + if(!merged) + goto malloc_err; + strncpy(merged, nam.naml$l_esa, + nam.naml$l_esl); + merged[nam.naml$l_esl] = '\0'; + } +#else + merged = OPENSSL_malloc(nam.nam$l_esl + 1); + if(!merged) + goto malloc_err; + strncpy(merged, nam.nam$l_esa, + nam.nam$l_esl); + merged[nam.nam$l_esl] = '\0'; +#endif + return(merged); + malloc_err: + DSOerr(DSO_F_VMS_MERGER, + ERR_R_MALLOC_FAILURE); + } + static char *vms_name_converter(DSO *dso, const char *filename) { int len = strlen(filename); diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c index af8586d754..4ce9a5d45c 100644 --- a/crypto/dso/dso_win32.c +++ b/crypto/dso/dso_win32.c @@ -1,4 +1,4 @@ -/* dso_win32.c */ +/* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */ /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL * project 2000. */ @@ -83,6 +83,8 @@ static int win32_finish(DSO *dso); static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg); #endif static char *win32_name_converter(DSO *dso, const char *filename); +static char *win32_merger(DSO *dso, const char *filespec1, + const char *filespec2); static DSO_METHOD dso_meth_win32 = { "OpenSSL 'win32' shared library method", @@ -97,6 +99,7 @@ static DSO_METHOD dso_meth_win32 = { #endif NULL, /* ctrl */ win32_name_converter, + win32_merger, NULL, /* init */ NULL /* finish */ }; @@ -248,6 +251,304 @@ static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname) return((DSO_FUNC_TYPE)sym); } +struct file_st + { + const char *node; int nodelen; + const char *device; int devicelen; + const char *predir; int predirlen; + const char *dir; int dirlen; + const char *file; int filelen; + } + +static struct file_st *win32_splitter(DSO *dso, const char *filename, + int assume_last_is_dir) + { + struct file_st *result = NULL; + enum { IN_NODE, IN_DEVICE, IN_FILE } position; + const char *start = filename; + + if (!filename) + { + DSOerr(DSO_F_WIN32_MERGER,DSO_R_NO_FILENAME); + goto err; + } + + result = OPENSSL_malloc(sizeof(struct file_st)); + if(result == NULL) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + + memset(result, 0, sizeof(struct file_st)); + position = IN_DEVICE; + + if(filename[0] == '\\' && filename[1] == '\\' + || filename[0] == '/' && filename[1] == '/') + { + position = IN_NODE; + filename += 2; + start = filename; + result->node = start; + } + + do + { + switch(filename[0]) + { + case ':': + if(position != IN_DEVICE) + { + DSOerr(DSO_F_WIN32_MERGER, + DSO_R_INCORRECT_FILE_SYNTAX); + goto err; + } + result->device = start; + result->devicelen = filename - start; + position = IN_FILE; + start = ++filename; + result->dir = start; + break; + case '\\': + case '/': + if(position == IN_NODE) + { + result->nodelen = filename - start; + position = IN_FILE; + start = ++filename; + result->dir = start; + } + else + { + filename++; + result->dirlen += filename - start; + } + break; + case '\0': + if(position == IN_NODE) + { + result->nodelen = filename - start; + } + else + { + if(filename - start > 0) + { + if (assume_last_is_dir) + { + result->devicelen += filename - start; + } + else + { + result->file = start; + result->filelen = filename - start; + } + } + } + break; + default: + filename++; + break; + } + } + while(*filename); + + if(!result->nodelen) result->node = NULL; + if(!result->devicelen) result->devicce = NULL; + if(!result->dirlen) result->dir = NULL; + if(!result->filelen) result->file = NULL; + + return(result); + } + +static char *win32_joiner(DSO *dso, const file_st *file_split) + { + int len = 0, offset = 0; + char *result = NULL; + const char *start; + + if(!file_split) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if(file_split->node) + { + len += 2 + file_split->nodelen; /* 2 for starting \\ */ + if(file_split->predir || file_split->dir || file_split->file) + len++; /* 1 for ending \ */ + } + else if(file_split->device) + { + len += file_split->devicelen + 1; /* 1 for ending : */ + } + len += file_split->predirlen; + if(file_split->predir && (file_split->dir || file_split->file)) + { + len++; /* 1 for ending \ */ + } + len += file_split->dirlen; + if(file_split->dir && file_split->file) + { + len++; /* 1 for ending \ */ + } + len += file_split->filelen; + + if(!len) + { + DSOerr(DSO_F_WIN32_MERGER, DSO_R_EMPTY_FILE_STRUCTURE); + return(NULL); + } + + result = OPENSSL_malloc(len + 1); + if (!result) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + + if(file_split->node) + { + strcpy(&result[offset], "\\\\"); offset += 2; + strncpy(&result[offset], file_split->node, + file_split->nodelen); offset += file_split->nodelen; + if(file_split->predir || file_split->dir || file_split->file) + { + result[offset] = '\\'; offset++; + } + } + else if(file_split->device) + { + strncpy(&result[offset], file_split->device, + file_split->devicelen); offset += file_split->devicelen; + result[offset] = ':'; offset++; + } + start = file_split->predir; + while(file_split->predirlen > (start - file_split->predir)) + { + const char *end = strnchr(start, '/', + file_split->predirlen - (start - file_split->predir)); + if(!end) + end = start + + file_split->predirlen + - (start - file_split->predir); + strncpy(&result[offset], start, + end - start); offset += end - start; + result[offset] = '\\'; offset++; + start = end + 1; + } + if(file_split->predir && (file_split->dir || file_split->file)) + { + result[offset] = '\\'; offset++; + } + start = file_split->dir; + while(file_split->dirlen > (start - file_split->dir)) + { + const char *end = strnchr(start, '/', + file_split->dirlen - (start - file_split->dir)); + if(!end) + end = start + + file_split->dirlen + - (start - file_split->dir); + strncpy(&result[offset], start, + end - start); offset += end - start; + result[offset] = '\\'; offset++; + start = end + 1; + } + if(file_split->dir && file_split->file) + { + result[offset] = '\\'; offset++; + } + strncpy(&result[offset], file_split->file, + file_split->filelen); offset += file_split->filelen; + result[offset] = '\0'; + return(result); + } + +static char *win32_merger(DSO *dso, const char *filespec1, const char *filespec2) + { + char *merged = NULL; + struct file_st *filespec1_split = NULL; + struct file_st *filespec2_split = NULL; + + if(!filespec1 && !filespec2) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_PASSED_NULL_PARAMETER); + return(NULL); + } + if (!filespec2) + { + merged = OPENSSL_malloc(strlen(filespec1) + 1); + if(!merged) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec1); + } + else if (!filespec1) + { + merged = OPENSSL_malloc(strlen(filespec2) + 1); + if(!merged) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + strcpy(merged, filespec2); + } + else + { + filespec1_split = win32_splitter(dso, filespec1, 1); + if (!filespec1_split) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_MALLOC_FAILURE); + return(NULL); + } + filespec2_split = win32_splitter(dso, filespec2, 0); + if (!filespec1_split) + { + DSOerr(DSO_F_WIN32_MERGER, + ERR_R_MALLOC_FAILURE); + OPENSSL_free(filespec1_split); + return(NULL); + } + + /* Fill in into filespec1_split */ + if (!filespec1_split->node && !filespec1_split->device) + { + filespec1_split->node = filespec2_split->node; + filespec1_split->nodelen = filespec2_split->nodelen; + filespec1_split->device = filespec2_split->device; + filespec1_split->devicelen = filespec2_split->devicelen; + } + if (!filespec1_split->dir) + { + filespec1_split->dir = filespec2_split->dir; + filespec1_split->dirlen = filespec2_split->dirlen; + } + else if (filespec1_split->dir[0] != '\\' + && filespec1_split->dir[0] != '/') + { + filespec1_split->predir = filespec2_split->dir; + filespec1_split->predirlen = filespec2_split->dirlen; + } + if (!filespec1_split->file) + { + filespec1_split->file = filespec2_split->file; + filespec1_split->filelen = filespec2_split->filelen; + } + + merged = win32_joiner(dso, filespec1_split); + } + return(merged); + } + static char *win32_name_converter(DSO *dso, const char *filename) { char *translated; -- 2.34.1