1/* 2 * load the sasl plugins 3 * $Id: mac_dyn_dlopen.c,v 1.4 2005/01/10 19:09:04 snsimon Exp $ 4 */ 5/* 6 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The name "Carnegie Mellon University" must not be used to 21 * endorse or promote products derived from this software without 22 * prior written permission. For permission or any other legal 23 * details, please contact 24 * Office of Technology Transfer 25 * Carnegie Mellon University 26 * 5000 Forbes Avenue 27 * Pittsburgh, PA 15213-3890 28 * (412) 268-4387, fax: (412) 268-7395 29 * tech-transfer@andrew.cmu.edu 30 * 31 * 4. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by Computing Services 34 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 35 * 36 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 37 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 38 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 39 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 40 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 41 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 42 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 43 */ 44 45 46#include <config.h> 47#include <stdlib.h> 48#include <string.h> 49#include <sasl.h> 50#include "saslint.h" 51 52#include <CodeFragments.h> 53#include <Errors.h> 54#include <Resources.h> 55#include <Strings.h> 56#include <Folders.h> 57 58#ifdef RUBBISH 59#include <FSpCompat.h> 60#endif 61 62/* 63 * The following data structure defines the structure of a code fragment 64 * resource. We can cast the resource to be of this type to access 65 * any fields we need to see. 66 */ 67struct CfrgHeader { 68 long res1; 69 long res2; 70 long version; 71 long res3; 72 long res4; 73 long filler1; 74 long filler2; 75 long itemCount; 76 char arrayStart; /* Array of externalItems begins here. */ 77}; 78typedef struct CfrgHeader CfrgHeader, *CfrgHeaderPtr, **CfrgHeaderPtrHand; 79 80/* 81 * The below structure defines a cfrag item within the cfrag resource. 82 */ 83struct CfrgItem { 84 OSType archType; 85 long updateLevel; 86 long currVersion; 87 long oldDefVersion; 88 long appStackSize; 89 short appSubFolder; 90 char usage; 91 char location; 92 long codeOffset; 93 long codeLength; 94 long res1; 95 long res2; 96 short itemSize; 97 Str255 name; /* This is actually variable sized. */ 98}; 99typedef struct CfrgItem CfrgItem; 100 101#ifndef TRUE 102#define TRUE 1 103#endif 104#ifndef FALSE 105#define FALSE 0 106#endif 107 108#if TARGET_API_MAC_CARBON 109#define SASL_PLUGIN_DIR "\p:sasl v2:carbon:biff" 110#else 111#define SASL_PLUGIN_DIR "\p:sasl v2:biff" 112#endif 113 114typedef struct lib_list 115{ 116 struct lib_list *next; 117 void *library; 118} lib_list_t; 119 120static lib_list_t *lib_list_head = NULL; 121 122/* 123 * add the passed extension 124 */ 125int _macsasl_get_fsspec(FSSpec *fspec, 126 void **libraryptr) 127{ 128 int rc; 129 CFragConnectionID connID; 130 Ptr dummy; 131 unsigned long offset = 0; 132 unsigned long length = kCFragGoesToEOF; 133 unsigned char package_name[255]; 134 Str255 error_text; 135 lib_list_t *newhead; 136 137 newhead = sasl_ALLOC(sizeof(lib_list_t)); 138 if(!newhead) return SASL_NOMEM; 139 140 package_name[0] = 0; 141 rc=GetDiskFragment(fspec,offset,length,package_name, 142 kLoadCFrag,&connID,&dummy,error_text); 143 if(rc!=0) { 144 sasl_FREE(newhead); 145 return rc; 146 } 147 148 newhead->library = (void *)connID; 149 newhead->next = lib_list_head; 150 lib_list_head = newhead; 151 152 *libraryptr = (void *)connID; 153 return SASL_OK; 154} 155 156int _sasl_locate_entry(void *library, const char *entryname, 157 void **entry_point) 158{ 159 int result; 160#if TARGET_API_MAC_CARBON 161 char cstr[256]; 162#endif 163 Str255 pentry; 164 CFragSymbolClass symClass; 165 OSErr rc; 166 167 if(!entryname) { 168 return SASL_BADPARAM; 169 } 170 171 if(!library) { 172 return SASL_BADPARAM; 173 } 174 175 if(!entry_point) { 176 return SASL_BADPARAM; 177 } 178 179#if TARGET_API_MAC_CARBON 180 strcpy(cstr,entryname); 181 CopyCStringToPascal(cstr, pentry); 182#else 183 strcpy(pentry,entryname); 184 c2pstr(pentry); 185#endif 186 187 rc = FindSymbol((CFragConnectionID)library,pentry,entry_point, &symClass); 188 if ((rc!=noErr) || (symClass==kDataCFragSymbol)) 189 return SASL_FAIL; 190 191 return SASL_OK; 192} 193 194static int _sasl_plugin_load(char *plugin, void *library, 195 const char *entryname, 196 int (*add_plugin)(const char *, void *)) 197{ 198 void *entry_point; 199 int result; 200 201 result = _sasl_locate_entry(library, entryname, &entry_point); 202 if(result == SASL_OK) { 203 result = add_plugin(plugin, entry_point); 204// if(result != SASL_OK) 205// _sasl_log(NULL, SASL_LOG_ERR, 206// "_sasl_plugin_load failed on %s for plugin: %s\n", 207// entryname, plugin); 208 } 209 210 return result; 211} 212 213/* 214 * does the passed string a occur and the end of string b? 215 */ 216int _macsasl_ends_in(char *a, char *b) 217{ 218 int alen=strlen(a); 219 int blen=strlen(b); 220 if(blen<alen) 221 return FALSE; 222 return (memcmp(a,b+(blen-alen),alen)==0); 223} 224 225/* 226 * scan the passed directory loading sasl extensions 227 */ 228int _macsasl_find_extensions_in_dir(short vref,long dir_id, 229 const add_plugin_list_t *entrypoints) 230{ 231 CInfoPBRec cinfo; 232 unsigned char aname[300]; 233 char plugname[256]; 234 int findex=0; 235 FSSpec a_plugin; 236 lib_list_t *library; 237 char *c; 238 const add_plugin_list_t *cur_ep; 239 240 while(TRUE) { 241 int os; 242 memset(&cinfo,0,sizeof(cinfo)); 243 aname[0] = 0; 244 cinfo.hFileInfo.ioVRefNum=vref; 245 cinfo.hFileInfo.ioNamePtr=aname; 246 cinfo.hFileInfo.ioFDirIndex=findex++; 247 cinfo.hFileInfo.ioDirID=dir_id; 248 os=PBGetCatInfo(&cinfo,FALSE); 249 if(os!=0) 250 return SASL_OK; 251 aname[aname[0]+1] = 0; 252 253 /* skip over non shlb files */ 254 if(!_macsasl_ends_in(".shlb",aname+1)) 255 continue; 256 os=FSMakeFSSpec(vref,dir_id,aname,&a_plugin); 257 if(os!=0) 258 continue; 259 260 /* skip "lib" and cut off suffix -- 261 this only need be approximate */ 262 strcpy(plugname, aname + 1); 263 c = strchr(plugname, (int)'.'); 264 if(c) *c = '\0'; 265 266 if (!_macsasl_get_fsspec(&a_plugin,&library)) 267 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) { 268 _sasl_plugin_load(plugname, library, cur_ep->entryname, 269 cur_ep->add_plugin); 270 /* If this fails, it's not the end of the world */ 271 } 272 } 273 return SASL_OK; 274} 275 276/* gets the list of mechanisms */ 277int _sasl_load_plugins(const add_plugin_list_t *entrypoints, 278 const sasl_callback_t *getpath_cb, 279 const sasl_callback_t *verifyfile_cb) 280{ 281 int rc; 282 short extensions_vref; 283 long extensions_dirid; 284 FSSpec sasl_dir; 285 /* find the extensions folder */ 286 rc=FindFolder(kOnSystemDisk,kExtensionFolderType,FALSE, 287 &extensions_vref,&extensions_dirid); 288 if(rc!=0) 289 return SASL_BADPARAM; 290 rc=FSMakeFSSpec(extensions_vref,extensions_dirid,SASL_PLUGIN_DIR,&sasl_dir); 291 /* 292 * if a plugin named biff exits or not we really dont care 293 * if it does get rc 0 if it does not get -43 (fnfErr) 294 * if the sasl dir doesnt exist we get -120 (dirNFFErr) 295 */ 296 if((rc!=0)&&(rc!=fnfErr)) 297 return SASL_BADPARAM; 298 /* 299 * now extensions_vref is volume 300 * sasl_dir.parID is dirid for sasl plugins folder 301 */ 302 303 return _macsasl_find_extensions_in_dir(extensions_vref,sasl_dir.parID,entrypoints); 304} 305 306int 307_sasl_done_with_plugins(void) 308{ 309 lib_list_t *libptr, *libptr_next; 310 311 for(libptr = lib_list_head; libptr; libptr = libptr_next) { 312 libptr_next = libptr->next; 313 if(libptr->library) 314 CloseConnection((CFragConnectionID*)&libptr->library); 315 sasl_FREE(libptr); 316 } 317 318 lib_list_head = NULL; 319 320 return SASL_OK; 321} 322