1/* 2 Copyright (c) 1990-2000 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, all these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 8*/ 9/* os2acl.c - access to OS/2 (LAN Server) ACLs 10 * 11 * Author: Kai Uwe Rommel <rommel@ars.de> 12 * Created: Mon Aug 08 1994 13 * 14 */ 15 16/* 17 * supported 32-bit compilers: 18 * - emx+gcc 19 * - IBM C Set++ 2.1 or newer 20 * - Watcom C/C++ 10.0 or newer 21 * 22 * supported 16-bit compilers: 23 * - MS C 6.00A 24 * - Watcom C/C++ 10.0 or newer 25 * 26 * supported OS/2 LAN environments: 27 * - IBM LAN Server/Requester 3.0, 4.0 and 5.0 (Warp Server) 28 * - IBM Peer 1.0 (Warp Connect) 29 */ 30 31#ifdef KUR 32 static char *rcsid = 33 "$Id: os2acl.c,v 1.3 1996/04/03 19:18:27 rommel Exp rommel $"; 34 static char *rcsrev = "$Revision: 1.3 $"; 35#endif 36 37/* 38 * $Log: os2acl.c,v $ 39 * Revision 1.3 1996/04/03 19:18:27 rommel 40 * minor fixes 41 * 42 * Revision 1.2 1996/03/30 22:03:52 rommel 43 * avoid frequent dynamic allocation for every call 44 * streamlined code 45 * 46 * Revision 1.1 1996/03/30 09:35:00 rommel 47 * Initial revision 48 * 49 */ 50 51#include <stdio.h> 52#include <stdlib.h> 53#include <string.h> 54#include <ctype.h> 55#include <malloc.h> 56 57#define INCL_NOPM 58#define INCL_DOS 59#define INCL_DOSERRORS 60#include <os2.h> 61 62#include "os2/os2acl.h" 63 64#define UNLEN 20 65 66#if defined(__WATCOMC__) && defined(__386__) && !defined(__32BIT__) 67#define __32BIT__ 68#endif 69 70#ifdef __32BIT__ 71typedef ULONG U_INT; 72#ifdef __EMX__ 73#define PSTR16 _far16ptr 74#define PTR16(x) _emx_32to16(x) 75#else /* other 32-bit */ 76#define PSTR16 PCHAR16 77#define PTR16(x) ((PCHAR16)(x)) 78#endif 79#else /* 16-bit */ 80typedef USHORT U_INT; 81#define PSTR16 PSZ 82#define PTR16(x) (x) 83#endif 84 85typedef struct access_list 86{ 87 char acl_ugname[UNLEN+1]; 88 char acl_pad; 89 USHORT acl_access; 90} 91ACCLIST; 92 93typedef struct access_info 94{ 95 PSTR16 acc_resource_name; 96 USHORT acc_attr; 97 USHORT acc_count; 98} 99ACCINFO; 100 101static ACCINFO *ai; 102static char *path, *data; 103 104#ifdef __32BIT__ 105 106#ifdef __EMX__ 107 108static USHORT (APIENTRY *_NetAccessGetInfo)(PSZ pszServer, PSZ pszResource, 109 USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail); 110static USHORT (APIENTRY *_NetAccessSetInfo)(PSZ pszServer, PSZ pszResource, 111 USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum); 112static USHORT (APIENTRY *_NetAccessAdd)(PSZ pszServer, 113 USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer); 114 115USHORT NetAccessGetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel, 116 PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail) 117{ 118 return (USHORT) 119 (_THUNK_PROLOG (4+4+2+4+2+4); 120 _THUNK_FLAT (pszServer); 121 _THUNK_FLAT (pszResource); 122 _THUNK_SHORT (sLevel); 123 _THUNK_FLAT (pbBuffer); 124 _THUNK_SHORT (cbBuffer); 125 _THUNK_FLAT (pcbTotalAvail); 126 _THUNK_CALLI (_emx_32to16(_NetAccessGetInfo))); 127} 128 129USHORT NetAccessSetInfo(PSZ pszServer, PSZ pszResource, USHORT sLevel, 130 PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum) 131{ 132 return (USHORT) 133 (_THUNK_PROLOG (4+4+2+4+2+2); 134 _THUNK_FLAT (pszServer); 135 _THUNK_FLAT (pszResource); 136 _THUNK_SHORT (sLevel); 137 _THUNK_FLAT (pbBuffer); 138 _THUNK_SHORT (cbBuffer); 139 _THUNK_SHORT (sParmNum); 140 _THUNK_CALLI (_emx_32to16(_NetAccessSetInfo))); 141} 142 143USHORT NetAccessAdd(PSZ pszServer, USHORT sLevel, 144 PVOID pbBuffer, USHORT cbBuffer) 145{ 146 return (USHORT) 147 (_THUNK_PROLOG (4+2+4+2); 148 _THUNK_FLAT (pszServer); 149 _THUNK_SHORT (sLevel); 150 _THUNK_FLAT (pbBuffer); 151 _THUNK_SHORT (cbBuffer); 152 _THUNK_CALLI (_emx_32to16(_NetAccessAdd))); 153} 154 155#else /* other 32-bit */ 156 157APIRET16 (* APIENTRY16 NetAccessGetInfo)(PCHAR16 pszServer, PCHAR16 pszResource, 158 USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, PVOID16 pcbTotalAvail); 159APIRET16 (* APIENTRY16 NetAccessSetInfo)(PCHAR16 pszServer, PCHAR16 pszResource, 160 USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer, USHORT sParmNum); 161APIRET16 (* APIENTRY16 NetAccessAdd)(PCHAR16 pszServer, 162 USHORT sLevel, PVOID16 pbBuffer, USHORT cbBuffer); 163 164#define _NetAccessGetInfo NetAccessGetInfo 165#define _NetAccessSetInfo NetAccessSetInfo 166#define _NetAccessAdd NetAccessAdd 167 168#if !defined(__IBMC__) || !defined(__TILED__) 169#define _tmalloc malloc 170#define _tfree free 171#endif 172 173#endif 174#else /* 16-bit */ 175 176USHORT (APIENTRY *NetAccessGetInfo)(PSZ pszServer, PSZ pszResource, 177 USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, PUSHORT pcbTotalAvail); 178USHORT (APIENTRY *NetAccessSetInfo)(PSZ pszServer, PSZ pszResource, 179 USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer, USHORT sParmNum); 180USHORT (APIENTRY *NetAccessAdd)(PSZ pszServer, 181 USHORT sLevel, PVOID pbBuffer, USHORT cbBuffer); 182 183#define _NetAccessGetInfo NetAccessGetInfo 184#define _NetAccessSetInfo NetAccessSetInfo 185#define _NetAccessAdd NetAccessAdd 186 187#define _tmalloc malloc 188#define _tfree free 189 190#define DosQueryProcAddr(handle, ord, name, funcptr) \ 191 DosGetProcAddr(handle, name, funcptr) 192#define DosQueryCurrentDir DosQCurDir 193#define DosQueryCurrentDisk DosQCurDisk 194 195#endif 196 197 198static BOOL acl_init(void) 199{ 200 static BOOL initialized, netapi_avail; 201 HMODULE netapi; 202 char buf[256]; 203 204 if (initialized) 205 return netapi_avail; 206 207 initialized = TRUE; 208 209 if (DosLoadModule(buf, sizeof(buf), "NETAPI", &netapi)) 210 return FALSE; 211 212 if (DosQueryProcAddr(netapi, 0, "NETACCESSGETINFO", (PFN *) &_NetAccessGetInfo) || 213 DosQueryProcAddr(netapi, 0, "NETACCESSSETINFO", (PFN *) &_NetAccessSetInfo) || 214 DosQueryProcAddr(netapi, 0, "NETACCESSADD", (PFN *) &_NetAccessAdd)) 215 return FALSE; 216 217#if defined(__WATCOMC__) && defined(__386__) 218 NetAccessGetInfo = (PVOID) (ULONG) (PVOID16) NetAccessGetInfo; 219 NetAccessSetInfo = (PVOID) (ULONG) (PVOID16) NetAccessSetInfo; 220 NetAccessAdd = (PVOID) (ULONG) (PVOID16) NetAccessAdd; 221#endif 222 223 if ((path = _tmalloc(CCHMAXPATH)) == NULL) 224 return FALSE; 225 if ((data = _tmalloc(ACL_BUFFERSIZE)) == NULL) 226 return FALSE; 227 if ((ai = _tmalloc(sizeof(ACCINFO))) == NULL) 228 return -1; 229 230 netapi_avail = TRUE; 231 232 return netapi_avail; 233} 234 235static void acl_mkpath(char *buffer, const char *source) 236{ 237 char *ptr; 238 static char cwd[CCHMAXPATH]; 239 static U_INT cwdlen; 240 U_INT cdrive; 241 ULONG drivemap; 242 243 if (isalpha((int)source[0]) && source[1] == ':') 244 buffer[0] = 0; /* fully qualified names */ 245 else 246 { 247 if (cwd[0] == 0) 248 { 249 DosQueryCurrentDisk(&cdrive, &drivemap); 250 cwd[0] = (char)(cdrive + '@'); 251 cwd[1] = ':'; 252 cwd[2] = '\\'; 253 cwdlen = sizeof(cwd) - 3; 254 DosQueryCurrentDir(0, cwd + 3, &cwdlen); 255 cwdlen = strlen(cwd); 256 } 257 258 if (source[0] == '/' || source[0] == '\\') 259 { 260 if (source[1] == '/' || source[1] == '\\') 261 buffer[0] = 0; /* UNC names */ 262 else 263 { 264 strncpy(buffer, cwd, 2); 265 buffer[2] = 0; 266 } 267 } 268 else 269 { 270 strcpy(buffer, cwd); 271 if (cwd[cwdlen - 1] != '\\' && cwd[cwdlen - 1] != '/') 272 strcat(buffer, "/"); 273 } 274 } 275 276 strcat(buffer, source); 277 278 for (ptr = buffer; *ptr; ptr++) 279 if (*ptr == '/') 280 *ptr = '\\'; 281 282 if (ptr[-1] == '\\') 283 ptr[-1] = 0; 284 285 strupr(buffer); 286} 287 288static int acl_bin2text(char *data, char *text) 289{ 290 ACCINFO *ai; 291 ACCLIST *al; 292 U_INT cnt, offs; 293 294 ai = (ACCINFO *) data; 295 al = (ACCLIST *) (data + sizeof(ACCINFO)); 296 297 offs = sprintf(text, "ACL1:%X,%d\n", 298 ai -> acc_attr, ai -> acc_count); 299 300 for (cnt = 0; cnt < ai -> acc_count; cnt++) 301 offs += sprintf(text + offs, "%s,%X\n", 302 al[cnt].acl_ugname, al[cnt].acl_access); 303 304 return strlen(text); 305} 306 307int acl_get(char *server, const char *resource, char *buffer) 308{ 309 USHORT datalen; 310 PSZ srv = NULL; 311 int rc; 312 313 if (!acl_init()) 314 return -1; 315 316 if (server) 317 srv = server; 318 319 acl_mkpath(path, resource); 320 datalen = 0; 321 322 rc = NetAccessGetInfo(srv, path, 1, data, ACL_BUFFERSIZE, &datalen); 323 324 if (rc == 0) 325 acl_bin2text(data, buffer); 326 327 return rc; 328} 329 330static int acl_text2bin(char *data, char *text, char *path) 331{ 332 ACCINFO *ai; 333 ACCLIST *al; 334 char *ptr, *ptr2; 335 U_INT cnt; 336 337 ai = (ACCINFO *) data; 338 ai -> acc_resource_name = PTR16(path); 339 340 if (sscanf(text, "ACL1:%hX,%hd", 341 &ai -> acc_attr, &ai -> acc_count) != 2) 342 return ERROR_INVALID_PARAMETER; 343 344 al = (ACCLIST *) (data + sizeof(ACCINFO)); 345 ptr = strchr(text, '\n') + 1; 346 347 for (cnt = 0; cnt < ai -> acc_count; cnt++) 348 { 349 ptr2 = strchr(ptr, ','); 350 strncpy(al[cnt].acl_ugname, ptr, ptr2 - ptr); 351 al[cnt].acl_ugname[ptr2 - ptr] = 0; 352 sscanf(ptr2 + 1, "%hx", &al[cnt].acl_access); 353 ptr = strchr(ptr, '\n') + 1; 354 } 355 356 return sizeof(ACCINFO) + ai -> acc_count * sizeof(ACCLIST); 357} 358 359int acl_set(char *server, const char *resource, char *buffer) 360{ 361 USHORT datalen; 362 PSZ srv = NULL; 363 364 if (!acl_init()) 365 return -1; 366 367 if (server) 368 srv = server; 369 370 acl_mkpath(path, resource); 371 372 ai -> acc_resource_name = PTR16(path); 373 ai -> acc_attr = 0; 374 ai -> acc_count = 0; 375 376 NetAccessAdd(srv, 1, ai, sizeof(ACCINFO)); 377 /* Ignore any errors, most probably because ACL already exists. */ 378 /* In any such case, try updating the existing ACL. */ 379 380 datalen = acl_text2bin(data, buffer, path); 381 382 return NetAccessSetInfo(srv, path, 1, data, datalen, 0); 383} 384 385/* end of os2acl.c */ 386