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