2 * Copyright (c) 1998, 1999, 2000 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/types.h>
40 #include <rx/rx_null.h>
45 #include <msecurity.h>
49 #include <openssl/des.h>
84 static struct rx_service
*prservice
;
86 prheader_disk pr_header
;
88 #define HEADERID PR_BADID
89 #define ILLEGAL_ID 0x40000000
90 #define ILLEGAL_GROUP 0x40000000
92 #define PRENTRY_DISK_SIZE (sizeof(prentry_disk) + PR_MAXGROUPS * sizeof(int32_t) + 16)
93 #define PRHEADER_DISK_SIZE (sizeof(prheader_disk) + 4 * PR_MAXGROUPS * sizeof(int32_t) + 16)
95 static void open_db (char *databaseprefix
, int flags
);
96 void prserver_close(void);
98 MDB
*nametoid
, *idtodata
;
108 int length
= PRHEADER_DISK_SIZE
;
109 struct mdb_datum key
, value
;
110 char pr_header_ydr
[PRHEADER_DISK_SIZE
];
113 char headerid
= htonl(HEADERID
);
115 if (ydr_encode_prheader_disk(&pr_header
, pr_header_ydr
, &length
) == NULL
)
116 err(1, "write_header");
118 key
.data
= &headerid
;
119 key
.length
= sizeof(headerid
);
121 value
.data
= pr_header_ydr
;
122 value
.length
= PRHEADER_DISK_SIZE
- length
;
124 code
= mdb_store(idtodata
, &key
, &value
);
135 int length
= PRHEADER_DISK_SIZE
;
136 struct mdb_datum key
, value
;
137 char headerid
= htonl(HEADERID
);
140 key
.data
= &headerid
;
141 key
.length
= sizeof(headerid
);
143 code
= mdb_fetch(idtodata
, &key
, &value
);
146 if (ydr_decode_prheader_disk(&pr_header
, value
.data
, &length
) == NULL
)
147 err(1, "read_header");
155 localize_name(const char *name
, Bool
*localp
)
157 static prname localname
;
162 strlcpy(localname
, name
, sizeof(localname
));
165 tmp
= strchr(localname
, '@');
167 if (!strcasecmp(tmp
+ 1, netinit_getrealm())) {
180 create_database(void)
182 pr_header
.version
= 0;
183 pr_header
.headerSize
= PRHEADER_DISK_SIZE
;
184 pr_header
.maxGroup
= -210; /* XXX */
186 /*XXX pr_header.orphan = 0;*/
187 pr_header
.usercount
= 0;
188 pr_header
.groupcount
= 0;
193 * read_prentry(): Fetch data from db, return a classic pr_entry
197 read_prentry(int id
, prentry
*pr_entry
)
199 prentry_disk disk_entry
;
202 status
= get_disk_entry(id
, &disk_entry
);
206 memset(pr_entry
, 0, sizeof(prentry
));
208 pr_entry
->flags
= disk_entry
.flags
;
209 pr_entry
->id
= disk_entry
.id
;
210 pr_entry
->cellid
= disk_entry
.cellid
;
211 pr_entry
->owner
= disk_entry
.owner
;
212 pr_entry
->creator
= disk_entry
.creator
;
213 pr_entry
->ngroups
= disk_entry
.ngroups
;
214 strlcpy(pr_entry
->name
, disk_entry
.name
, sizeof(pr_entry
->name
));
216 if (disk_entry
.owned
.len
> 0)
217 pr_entry
->owned
= disk_entry
.owned
.val
[0];
219 for (i
= 0; i
< PRSIZE
&& i
< disk_entry
.entries
.len
; i
++)
220 pr_entry
->entries
[i
] = disk_entry
.entries
.val
[i
];
222 mlog_log (MDEBPRDB
, "read_prentry id: %d owner: %d creator: %d name: %s",
223 pr_entry
->id
, pr_entry
->owner
,
224 pr_entry
->creator
, pr_entry
->name
);
230 * store_disk_entry(): marshal prentry_disk and store in db
234 store_disk_entry(prentry_disk
*entry
)
236 char pr_entry_disk_ydr
[PRENTRY_DISK_SIZE
];
237 int length
= PRENTRY_DISK_SIZE
;
238 struct mdb_datum key
, value
;
241 mlog_log (MDEBPRDB
, "store_disk_entry id: %d owner: %d creator: %d name: %s",
242 entry
->id
, entry
->owner
,
243 entry
->creator
, entry
->name
);
245 if (ydr_encode_prentry_disk((prentry_disk
*) entry
, pr_entry_disk_ydr
, &length
) == NULL
)
246 err(1, "store_disk_entry");
248 id
= htonl(entry
->id
);
250 key
.length
= sizeof(id
);
252 value
.data
= pr_entry_disk_ydr
;
253 value
.length
= PRENTRY_DISK_SIZE
- length
;
255 return mdb_store(idtodata
, &key
, &value
);
259 * write_prentry(): update db with classic prentry
263 write_prentry(prentry
*pr_entry
)
265 prentry_disk disk_entry
;
268 memset(&disk_entry
, 0, sizeof(prentry_disk
));
270 disk_entry
.flags
= pr_entry
->flags
;
271 disk_entry
.id
= pr_entry
->id
;
272 disk_entry
.cellid
= pr_entry
->cellid
;
273 disk_entry
.owner
= pr_entry
->owner
;
274 disk_entry
.creator
= pr_entry
->creator
;
275 disk_entry
.ngroups
= pr_entry
->ngroups
;
276 /* disk_entry.owned = pr_entry->owned; XXX */
277 strlcpy(disk_entry
.name
, pr_entry
->name
, sizeof(disk_entry
.name
));
279 for (i
= 0; i
< PRSIZE
&& i
< pr_entry
->count
; i
++)
280 disk_entry
.entries
.val
[i
] = pr_entry
->entries
[i
];
282 disk_entry
.entries
.len
= i
;
284 return store_disk_entry(&disk_entry
);
292 write_name(prentry
*pr_entry
)
294 struct mdb_datum key
, value
;
295 int32_t id
= htonl(pr_entry
->id
);
297 key
.data
= pr_entry
->name
;
298 key
.length
= strlen(pr_entry
->name
);
301 value
.length
= sizeof(id
);
303 return mdb_store(nametoid
, &key
, &value
);
311 insert_entry(prentry
*pr_entry
)
313 char *pr_entry_disk_ydr
;
317 char *name
= pr_entry
->name
;
319 status
= get_ydr_disk_entry(pr_entry
->id
, &pr_entry_disk_ydr
);
322 if (status
!= PRNOENT
)
325 status
= conv_name_to_id(name
, &id
);
328 if (status
!= PRNOENT
)
331 status
= write_name(pr_entry
);
335 return write_prentry(pr_entry
);
337 /* XXX: update owned and nextOwned */
338 /* XXX update header */
339 /* write_header(); */
347 create_group(const char *name
,
355 memset(&pr_entry
, 0, sizeof(pr_entry
));
356 pr_entry
.flags
= PRGRP
;
358 pr_entry
.owner
= owner
;
359 pr_entry
.creator
= creator
;
360 strlcpy(pr_entry
.name
, name
, PR_MAXNAMELEN
);
362 status
= insert_entry(&pr_entry
);
374 create_user(const char *name
,
382 memset(&pr_entry
, 0, sizeof(pr_entry
));
385 pr_entry
.owner
= owner
;
386 pr_entry
.creator
= creator
;
387 strlcpy(pr_entry
.name
, name
, PR_MAXNAMELEN
);
389 status
= insert_entry(&pr_entry
);
401 addtogroup (int32_t uid
, int32_t gid
)
403 prentry_disk uid_entry
;
404 prentry_disk gid_entry
;
405 int error
, i
, tmp1
, tmp2
;
407 mlog_log (MDEBPRDB
, "addtogroup");
409 error
= get_disk_entry(uid
, &uid_entry
);
413 error
= get_disk_entry(gid
, &gid_entry
);
417 if (uid_entry
.entries
.len
>= (PR_MAXGROUPS
- 1)
418 || gid_entry
.entries
.len
>= (PR_MAXLIST
- 1))
422 while (uid_entry
.entries
.val
[i
] < gid
&& i
< uid_entry
.entries
.len
)
426 for (; i
< uid_entry
.entries
.len
; i
++) {
427 tmp2
= uid_entry
.entries
.val
[i
];
428 uid_entry
.entries
.val
[i
] = tmp1
;
431 uid_entry
.entries
.val
[uid_entry
.entries
.len
] = tmp1
;
432 uid_entry
.entries
.len
++;
435 while (gid_entry
.entries
.val
[i
] < uid
&& i
< gid_entry
.entries
.len
)
439 for (; i
< gid_entry
.entries
.len
; i
++) {
440 tmp2
= gid_entry
.entries
.val
[i
];
441 gid_entry
.entries
.val
[i
] = tmp1
;
444 gid_entry
.entries
.val
[gid_entry
.entries
.len
] = tmp1
;
445 gid_entry
.entries
.len
++;
447 if ((error
= store_disk_entry(&uid_entry
)) != 0)
450 if ((error
= store_disk_entry(&gid_entry
)) != 0)
461 removefromgroup (int32_t uid
, int32_t gid
)
463 prentry_disk uid_entry
;
464 prentry_disk gid_entry
;
467 mlog_log (MDEBPRDB
, "removefromgroup");
469 error
= get_disk_entry(uid
, &uid_entry
);
473 error
= get_disk_entry(gid
, &gid_entry
);
479 while (uid_entry
.entries
.val
[i
] < gid
&& i
< uid_entry
.entries
.len
)
482 if (uid_entry
.entries
.val
[i
] != gid
)
485 for (i
++; i
< uid_entry
.entries
.len
; i
++)
486 uid_entry
.entries
.val
[i
- 1] = uid_entry
.entries
.val
[i
];
488 uid_entry
.entries
.len
--;
491 while (gid_entry
.entries
.val
[i
] < uid
&& i
< gid_entry
.entries
.len
)
494 if (gid_entry
.entries
.val
[i
] != uid
)
497 for (i
++; i
< gid_entry
.entries
.len
; i
++)
498 gid_entry
.entries
.val
[i
- 1] = gid_entry
.entries
.val
[i
];
500 gid_entry
.entries
.len
--;
502 /* XXX may leave database inconsistent ?? */
504 if ((error
= store_disk_entry(&uid_entry
)) != 0)
507 if ((error
= store_disk_entry(&gid_entry
)) != 0)
519 listelements (int32_t id
, prlist
*elist
, Bool default_id_p
)
521 prentry_disk disk_entry
;
524 error
= get_disk_entry(id
, &disk_entry
);
529 elist
->len
= disk_entry
.entries
.len
+ 3;
531 elist
->len
= disk_entry
.entries
.len
;
533 elist
->val
= malloc(sizeof(*elist
->val
) * elist
->len
);
534 if (elist
->val
== NULL
)
535 return ENOMEM
; /* XXX */
538 /* XXX should be sorted */
540 for (i
= 0; i
< disk_entry
.entries
.len
; i
++)
541 elist
->val
[i
] = disk_entry
.entries
.val
[i
];
545 elist
->val
[++i
] = PR_ANYUSERID
;
546 elist
->val
[++i
] = PR_AUTHUSERID
;
557 get_ydr_disk_entry(int id
, char **buf
)
559 struct mdb_datum key
, value
;
565 key
.length
= sizeof(id
);
567 status
= mdb_fetch(idtodata
, &key
, &value
);
568 if (status
== ENOENT
)
581 get_disk_entry(int id
, prentry_disk
*entry
)
583 char *pr_entry_disk_ydr
;
584 int length
= PRENTRY_DISK_SIZE
; /* XXX maxsize in mdb??? */
587 status
= get_ydr_disk_entry(id
, &pr_entry_disk_ydr
);
591 if (ydr_decode_prentry_disk(entry
, pr_entry_disk_ydr
, &length
) == NULL
)
592 err(1, "get_disk_entry");
602 conv_name_to_id(const char *name
, int *id
)
604 struct mdb_datum key
, value
;
607 key
.data
= strdup(name
); /*XXX*/
608 key
.length
= strlen(name
);
610 status
= mdb_fetch(nametoid
, &key
, &value
);
611 if (status
== ENOENT
)
614 *id
= ntohl(*((int *)value
.data
));
626 conv_id_to_name(int id
, char *name
)
631 status
= read_prentry(id
, &pr_entry
);
634 strlcpy(name
, pr_entry
.name
, PR_MAXNAMELEN
);
643 next_free_group_id(int *id
)
645 pr_header
.maxGroup
--; /* XXX */
646 if (pr_header
.maxGroup
== ILLEGAL_GROUP
) {
647 pr_header
.maxGroup
++;
653 *id
= pr_header
.maxGroup
;
662 next_free_user_id(int *id
)
664 pr_header
.maxID
++; /* XXX */
665 if (pr_header
.maxID
== ILLEGAL_ID
) {
672 *id
= pr_header
.maxID
;
681 open_db (char *databaseprefix
, int flags
)
683 char database
[MAXPATHLEN
];
685 if (databaseprefix
== NULL
)
686 databaseprefix
= MILKO_SYSCONFDIR
;
688 snprintf (database
, sizeof(database
), "%s/pr_idtodata",
691 mlog_log (MDEBPR
, "Loading db from file %s\n", database
);
693 idtodata
= mdb_open(database
, flags
, 0600);
694 if (idtodata
== NULL
)
695 err(1, "failed open (%s)", database
);
698 snprintf (database
, sizeof(database
), "%s/pr_nametoid",
701 mlog_log (MDEBPR
, "Loading db from file %s\n", database
);
703 nametoid
= mdb_open(database
, flags
, 0600);
704 if (nametoid
== NULL
)
705 err(1, "failed open (%s)", database
);
724 prserver_create (char *databaseprefix
)
728 open_db (databaseprefix
, O_RDWR
|O_CREAT
|O_EXCL
|O_BINARY
);
730 printf ("Creating a new pr-database.\n");
735 status = create_group((N), (I), (O), (G)); \
737 errx (1, "failed when creating %s with error %d", \
741 M("system:administrators", PR_SYSADMINID
, PR_SYSADMINID
, PR_SYSADMINID
);
742 M("system:anyuser", PR_ANYUSERID
, PR_SYSADMINID
, PR_SYSADMINID
);
743 M("system:authuser", PR_AUTHUSERID
, PR_SYSADMINID
, PR_SYSADMINID
);
744 M("anonymous", PR_ANONYMOUSID
, PR_SYSADMINID
, PR_SYSADMINID
);
758 prserver_init(char *databaseprefix
)
760 open_db(databaseprefix
, O_RDWR
|O_BINARY
);
770 static char *cell
= NULL
;
771 static char *realm
= NULL
;
772 static char *srvtab_file
= NULL
;
773 static char *log_file
= "syslog";
774 static char *debug_levels
= NULL
;
775 static int no_auth
= 0;
776 static int do_help
= 0;
777 static char *databasedir
= NULL
;
778 static int do_create
= 0;
780 static struct agetargs args
[] = {
781 {"cell", 0, aarg_string
, &cell
, "what cell to use"},
782 {"realm", 0, aarg_string
, &realm
, "what realm to use"},
783 {"debug", 'd', aarg_string
, &debug_levels
, "debug level"},
784 {"log", 'l', aarg_string
, &log_file
,
785 "where to write log (stderr, syslog (default), or path to file)"},
786 {"srvtab", 0, aarg_string
, &srvtab_file
, "what srvtab to use"},
787 {"noauth", 0, aarg_flag
, &no_auth
, "disable authentication checks"},
788 {"help", 'h', aarg_flag
, &do_help
, "help"},
789 {"dbdir", 0, aarg_string
, &databasedir
, "where to store the db"},
790 {"create", 0, aarg_flag
, &do_create
, "create new database"},
791 { NULL
, 0, aarg_end
, NULL
}
801 aarg_printusage (args
, NULL
, "", AARG_GNUSTYLE
);
810 main(int argc
, char **argv
)
816 setprogname (argv
[0]);
818 if (agetarg (args
, argc
, argv
, &optind
, AARG_GNUSTYLE
)) {
826 printf("unknown option %s", *argv
);
834 sec_disable_superuser_check ();
836 method
= log_open (getprogname(), log_file
);
838 errx (1, "log_open failed");
839 cell_init(0, method
);
842 printf ("ptserver booting");
844 mlog_loginit (method
, milko_deb_units
, MDEFAULT_LOG
);
847 mlog_log_set_level (debug_levels
);
850 cell_setthiscell (cell
);
852 network_kerberos_init (srvtab_file
);
855 prserver_create (databasedir
);
859 ret
= prserver_init(databasedir
);
861 errx (1, "prserver_init: error %d", ret
);
863 ret
= network_init(htons(afsprport
), "pr", PR_SERVICE_ID
,
864 PR_ExecuteRequest
, &prservice
, realm
);
866 errx (1, "network_init returned %d", ret
);
868 mlog_log (MDEBWARN
, "started");
870 rx_SetMaxProcs(prservice
,5) ;