1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * Event Log Service RPC (LOGR) interface definition. 29 */ 30 #include <sys/utsname.h> 31 #include <unistd.h> 32 #include <strings.h> 33 #include <libmlrpc/libmlrpc.h> 34 #include <smbsrv/libsmb.h> 35 #include <smbsrv/nmpipes.h> 36 #include <smbsrv/libmlsvc.h> 37 #include <smbsrv/ndl/eventlog.ndl> 38 39 40 #define LOGR_FWD +1 41 #define LOGR_REW -1 42 #define LOGR_RECORD_SIGNATURE 0x654C664C 43 44 #define LOGR_PRI(p) ((p) & LOG_PRIMASK) 45 #define LOGR_WNSTRLEN(S) ((strlen((S)) + 1) * sizeof (smb_wchar_t)) 46 47 #define LOGR_MSG_DWORD_OFFSET 12 48 #define LOGR_MSG_WORD_OFFSET 4 49 50 /* 51 * READ flags for EventLogRead 52 * 53 * EVENTLOG_SEEK_READ 54 * The read operation proceeds from the record specified by the 55 * dwRecordOffset parameter. This flag cannot be used with 56 * EVENTLOG_SEQUENTIAL_READ. 57 * 58 * EVENTLOG_SEQUENTIAL_READ 59 * The read operation proceeds sequentially from the last call to the 60 * ReadEventLog function using this handle. This flag cannot be used 61 * with EVENTLOG_SEEK_READ. 62 * 63 * If the buffer is large enough, more than one record can be read at 64 * the specified seek position; you must specify one of the following 65 * flags to indicate the direction for successive read operations. 66 * 67 * EVENTLOG_FORWARDS_READ 68 * The log is read in chronological order. This flag cannot be used 69 * with EVENTLOG_BACKWARDS_READ. 70 * 71 * EVENTLOG_BACKWARDS_READ 72 * The log is read in reverse chronological order. This flag cannot be 73 * used with EVENTLOG_FORWARDS_READ. 74 */ 75 #define EVENTLOG_SEQUENTIAL_READ 0x0001 76 #define EVENTLOG_SEEK_READ 0x0002 77 #define EVENTLOG_FORWARDS_READ 0x0004 78 #define EVENTLOG_BACKWARDS_READ 0x0008 79 80 /* 81 * The types of events that can be logged. 82 */ 83 #define EVENTLOG_SUCCESS 0x0000 84 #define EVENTLOG_ERROR_TYPE 0x0001 85 #define EVENTLOG_WARNING_TYPE 0x0002 86 #define EVENTLOG_INFORMATION_TYPE 0x0004 87 #define EVENTLOG_AUDIT_SUCCESS 0x0008 88 #define EVENTLOG_AUDIT_FAILURE 0x0010 89 90 /* 91 * Event Identifiers 92 * 93 * Event identifiers uniquely identify a particular event. Each event 94 * source can define its own numbered events and the description strings 95 * to which they are mapped. Event viewers can present these strings to 96 * the user. They should help the user understand what went wrong and 97 * suggest what actions to take. Direct the description at users solving 98 * their own problems, not at administrators or support technicians. 99 * Make the description clear and concise and avoid culture-specific 100 * phrases. 101 * 102 * The following diagram illustrates the format of an event identifier. 103 * 104 * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 105 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 106 * +---+-+-+-----------------------+-------------------------------+ 107 * |Sev|C|R| Facility | Code | 108 * +---+-+-+-----------------------+-------------------------------+ 109 * 110 * Sev 111 * Indicates the severity. This is one of the following values: 112 * 00 - Success 113 * 01 - Informational 114 * 10 - Warning 115 * 11 - Error 116 * 117 * C 118 * Indicates a customer code (1) or a system code (0). 119 * R 120 * Reserved bit. 121 * Facility 122 * Facility code. 123 * Code 124 * Status code for the facility. 125 */ 126 #define EVENTID_SEVERITY_SUCCESS 0x00000000 127 #define EVENTID_SEVERITY_INFO 0x40000000 128 #define EVENTID_SEVERITY_WARNING 0x80000000 129 #define EVENTID_SEVERITY_ERROR 0xC0000000 130 131 #define EVENTID_SYSTEM_CODE 0x00000000 132 #define EVENTID_CUSTOMER_CODE 0x20000000 133 134 static int logr_s_EventLogClose(void *, ndr_xa_t *); 135 static int logr_s_EventLogQueryCount(void *, ndr_xa_t *); 136 static int logr_s_EventLogGetOldestRec(void *, ndr_xa_t *); 137 static int logr_s_EventLogOpen(void *, ndr_xa_t *); 138 static int logr_s_EventLogRead(void *, ndr_xa_t *); 139 140 static ndr_stub_table_t logr_stub_table[] = { 141 { logr_s_EventLogClose, LOGR_OPNUM_EventLogClose }, 142 { logr_s_EventLogQueryCount, LOGR_OPNUM_EventLogQueryCount }, 143 { logr_s_EventLogGetOldestRec, LOGR_OPNUM_EventLogGetOldestRec }, 144 { logr_s_EventLogOpen, LOGR_OPNUM_EventLogOpen }, 145 { logr_s_EventLogRead, LOGR_OPNUM_EventLogRead }, 146 {0} 147 }; 148 149 static ndr_service_t logr_service = { 150 "LOGR", /* name */ 151 "Event Log Service", /* desc */ 152 "\\eventlog", /* endpoint */ 153 PIPE_NTSVCS, /* sec_addr_port */ 154 "82273fdc-e32a-18c3-3f78-827929dc23ea", 0, /* abstract */ 155 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 156 0, /* no bind_instance_size */ 157 0, /* no bind_req() */ 158 0, /* no unbind_and_close() */ 159 0, /* use generic_call_stub() */ 160 &TYPEINFO(logr_interface), /* interface ti */ 161 logr_stub_table /* stub_table */ 162 }; 163 164 /* 165 * logr_initialize 166 * 167 * This function registers the LOGR RPC interface with the RPC runtime 168 * library. It must be called in order to use either the client side 169 * or the server side functions. 170 */ 171 void 172 logr_initialize(void) 173 { 174 (void) ndr_svc_register(&logr_service); 175 logr_init(); 176 } 177 178 void 179 logr_finalize(void) 180 { 181 logr_fini(); 182 } 183 184 /* 185 * logr_hdlookup 186 * 187 * Handle lookup wrapper to validate the local service and/or manager context. 188 */ 189 static ndr_handle_t * 190 logr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id) 191 { 192 ndr_handle_t *hd; 193 logr_context_t *ctx; 194 195 if ((hd = ndr_hdlookup(mxa, id)) == NULL) 196 return (NULL); 197 198 if ((ctx = (logr_context_t *)hd->nh_data) == NULL) 199 return (NULL); 200 201 if (ctx->lc_source_name == NULL) 202 return (NULL); 203 204 return (hd); 205 } 206 207 /* 208 * logr_context_data_free 209 * 210 * Callback to free the context data associated with local service 211 * and/or manager context. 212 */ 213 static void 214 logr_context_data_free(void *ctxp) 215 { 216 logr_context_t *ctx = (logr_context_t *)ctxp; 217 218 if (ctx == NULL) 219 return; 220 221 free(ctx->lc_source_name); 222 free(ctx->lc_cached_read_data->rd_log); 223 free(ctx->lc_cached_read_data); 224 free(ctx); 225 ctx = NULL; 226 } 227 228 /* 229 * logr_hdalloc 230 * 231 * Handle allocation wrapper to setup the local manager context. 232 */ 233 static ndr_hdid_t * 234 logr_hdalloc(ndr_xa_t *mxa, char *logname) 235 { 236 logr_context_t *ctx; 237 238 if ((ctx = malloc(sizeof (logr_context_t))) == NULL) 239 return (NULL); 240 bzero(ctx, sizeof (logr_context_t)); 241 242 ctx->lc_source_name = strdup(logname); 243 if (ctx->lc_source_name == NULL) { 244 free(ctx); 245 return (NULL); 246 } 247 248 if (logr_get_snapshot(ctx) != 0) { 249 free(ctx->lc_source_name); 250 free(ctx); 251 return (NULL); 252 } 253 254 return (ndr_hdalloc(mxa, ctx)); 255 } 256 257 /* 258 * logr_s_EventLogClose 259 * 260 * This is a request to close the LOGR interface specified by handle. 261 * Free the handle and associated resources, and zero out the result 262 * handle for the client. 263 */ 264 static int 265 logr_s_EventLogClose(void *arg, ndr_xa_t *mxa) 266 { 267 struct logr_EventLogClose *param = arg; 268 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 269 ndr_handle_t *hd; 270 271 if ((hd = ndr_hdlookup(mxa, id)) == NULL) { 272 bzero(¶m->result_handle, sizeof (logr_handle_t)); 273 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 274 return (NDR_DRC_OK); 275 } 276 logr_context_data_free(hd->nh_data); 277 ndr_hdfree(mxa, id); 278 279 bzero(¶m->result_handle, sizeof (logr_handle_t)); 280 param->status = NT_STATUS_SUCCESS; 281 282 return (NDR_DRC_OK); 283 } 284 285 /* 286 * logr_s_EventLogOpen 287 * 288 * Open the event log. Not supported yet. 289 */ 290 /*ARGSUSED*/ 291 static int 292 logr_s_EventLogOpen(void *arg, ndr_xa_t *mxa) 293 { 294 struct logr_EventLogOpen *param = arg; 295 ndr_hdid_t *id = NULL; 296 ndr_handle_t *hd; 297 char *log_name = NULL; 298 299 if (!ndr_is_admin(mxa)) { 300 bzero(¶m->handle, sizeof (logr_handle_t)); 301 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 302 return (NDR_DRC_OK); 303 } 304 305 if (param->log_name.length != 0) 306 log_name = (char *)param->log_name.str; 307 308 if (!logr_is_supported(log_name)) { 309 bzero(¶m->handle, sizeof (logr_handle_t)); 310 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 311 return (NDR_DRC_OK); 312 } 313 314 id = logr_hdalloc(mxa, log_name); 315 if (id && ((hd = logr_hdlookup(mxa, id)) != NULL)) { 316 hd->nh_data_free = logr_context_data_free; 317 bcopy(id, ¶m->handle, sizeof (logr_handle_t)); 318 param->status = NT_STATUS_SUCCESS; 319 } else { 320 bzero(¶m->handle, sizeof (logr_handle_t)); 321 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); 322 } 323 324 return (NDR_DRC_OK); 325 } 326 327 /* 328 * logr_s_EventLogQueryCount 329 * 330 * take a snapshot from system log, assign it to the given handle. 331 * return number of log entries in the snapshot as result of RPC 332 * call. 333 */ 334 static int 335 logr_s_EventLogQueryCount(void *arg, ndr_xa_t *mxa) 336 { 337 struct logr_EventLogQueryCount *param = arg; 338 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 339 ndr_handle_t *hd; 340 logr_context_t *ctx; 341 logr_read_data_t *data; 342 343 if ((hd = logr_hdlookup(mxa, id)) == NULL) { 344 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 345 return (NDR_DRC_OK); 346 } 347 348 ctx = (logr_context_t *)hd->nh_data; 349 data = ctx->lc_cached_read_data; 350 351 param->rec_num = data->rd_tot_recnum; 352 param->status = NT_STATUS_SUCCESS; 353 return (NDR_DRC_OK); 354 } 355 356 /* 357 * logr_s_EventLogGetOldestRec 358 * 359 * Return oldest record number in the snapshot as result of RPC call. 360 */ 361 static int 362 logr_s_EventLogGetOldestRec(void *arg, ndr_xa_t *mxa) 363 { 364 struct logr_EventLogGetOldestRec *param = arg; 365 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 366 ndr_handle_t *hd; 367 logr_context_t *ctx; 368 logr_read_data_t *data; 369 370 if ((hd = logr_hdlookup(mxa, id)) == NULL) { 371 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 372 return (NDR_DRC_OK); 373 } 374 375 ctx = (logr_context_t *)hd->nh_data; 376 data = ctx->lc_cached_read_data; 377 378 param->oldest_rec = data->rd_log->li_idx - data->rd_tot_recnum + 1; 379 380 param->status = NT_STATUS_SUCCESS; 381 return (NDR_DRC_OK); 382 } 383 384 /* 385 * logr_set_event_typeid 386 * 387 * Map the local system log priority to the event type and event ID 388 * for Windows events. 389 */ 390 void 391 logr_set_event_typeid(int le_pri, WORD *etype, DWORD *eid) 392 { 393 switch (LOGR_PRI(le_pri)) { 394 case LOG_EMERG: 395 case LOG_ALERT: 396 case LOG_CRIT: 397 case LOG_ERR: 398 *eid = EVENTID_SEVERITY_ERROR; 399 *etype = EVENTLOG_ERROR_TYPE; 400 break; 401 case LOG_WARNING: 402 *eid = EVENTID_SEVERITY_WARNING; 403 *etype = EVENTLOG_WARNING_TYPE; 404 break; 405 case LOG_NOTICE: 406 case LOG_INFO: 407 case LOG_DEBUG: 408 *eid = EVENTID_SEVERITY_INFO; 409 *etype = EVENTLOG_INFORMATION_TYPE; 410 break; 411 default: 412 *eid = EVENTID_SEVERITY_SUCCESS; 413 *etype = EVENTLOG_SUCCESS; 414 } 415 } 416 417 /* 418 * logr_get_entry 419 * 420 * Gets a log entry. 421 */ 422 static logr_entry_t * 423 logr_get_entry(logr_info_t *linfo, int entno) 424 { 425 return (&linfo->li_entry[entno]); 426 } 427 428 /* 429 * logr_set_logrecord 430 * 431 * Fill a Windows event record based on a local system log record. 432 */ 433 static void 434 logr_set_logrecord(char *src_name, logr_entry_t *le, 435 DWORD recno, logr_record_t *rec) 436 { 437 int srcname_len = 0, hostname_len = 0, len; 438 int str_offs, sh_len; 439 smb_wchar_t wcs_hostname[MAXHOSTNAMELEN]; 440 smb_wchar_t wcs_srcname[SYS_NMLN * 2]; 441 442 (void) smb_mbstowcs(wcs_srcname, src_name, 443 strlen(src_name) + 1); 444 srcname_len = LOGR_WNSTRLEN(src_name); 445 446 /* Because, Solaris allows remote logging, need to get hostname here */ 447 (void) smb_mbstowcs(wcs_hostname, le->le_hostname, 448 strlen(le->le_hostname) + 1); 449 hostname_len = LOGR_WNSTRLEN(le->le_hostname); 450 451 sh_len = srcname_len + hostname_len; 452 str_offs = LOGR_MSG_DWORD_OFFSET * sizeof (DWORD) + 453 LOGR_MSG_WORD_OFFSET * sizeof (WORD) + sh_len; 454 455 rec->Length1 = sizeof (logr_record_t); 456 rec->Reserved = LOGR_RECORD_SIGNATURE; 457 rec->RecordNumber = recno; 458 rec->TimeGenerated = le->le_timestamp.tv_sec; 459 rec->TimeWritten = le->le_timestamp.tv_sec; 460 logr_set_event_typeid(le->le_pri, &rec->EventType, &rec->EventID); 461 rec->NumStrings = 1; 462 rec->EventCategory = 0; 463 rec->ReservedFlags = 0; 464 rec->ClosingRecordNumber = 0; 465 rec->StringOffset = str_offs; 466 rec->UserSidLength = 0; 467 rec->UserSidOffset = 0; 468 rec->DataLength = 0; 469 rec->DataOffset = 0; 470 471 bzero(rec->info, LOGR_MAXENTRYLEN); 472 (void) memcpy(rec->info, wcs_srcname, srcname_len); 473 (void) memcpy(rec->info + srcname_len, wcs_hostname, hostname_len); 474 475 len = strlen(le->le_msg) + 1; 476 if (len > 0) 477 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 478 (void) smb_mbstowcs((smb_wchar_t *)(rec->info + sh_len), 479 le->le_msg, len); 480 481 rec->Length2 = sizeof (logr_record_t); 482 } 483 484 /* 485 * logr_s_EventLogRead 486 * 487 * Reads a whole number of entries from system log. The function can 488 * read log entries in chronological or reverse chronological order. 489 */ 490 static int 491 logr_s_EventLogRead(void *arg, ndr_xa_t *mxa) 492 { 493 struct logr_EventLogRead *param = arg; 494 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 495 ndr_handle_t *hd; 496 logr_read_data_t *rdata; 497 logr_entry_t *le; 498 DWORD ent_no, ent_num, ent_remain; 499 logr_record_t *rec; 500 BYTE *buf; 501 int dir, ent_per_req, iter; 502 logr_context_t *ctx; 503 504 if ((hd = logr_hdlookup(mxa, id)) == NULL) { 505 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); 506 return (NDR_DRC_OK); 507 } 508 509 ctx = (logr_context_t *)hd->nh_data; 510 rdata = ctx->lc_cached_read_data; 511 if (rdata == NULL) { 512 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); 513 return (NDR_DRC_OK); 514 } 515 516 dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ? 517 LOGR_FWD : LOGR_REW; 518 519 if (param->read_flags & EVENTLOG_SEEK_READ) 520 rdata->rd_last_sentrec = param->rec_offset; 521 else if (rdata->rd_first_read) 522 /* 523 * set last record number which is read for 524 * the first iteration of sequential read. 525 */ 526 rdata->rd_last_sentrec = (dir == LOGR_FWD) 527 ? (rdata->rd_log->li_idx - rdata->rd_tot_recnum) 528 : rdata->rd_log->li_idx; 529 530 ent_remain = (dir == LOGR_FWD) 531 ? (rdata->rd_tot_recnum - rdata->rd_last_sentrec) 532 : rdata->rd_last_sentrec; 533 534 /* 535 * function should return as many whole log entries as 536 * will fit in the buffer; it should not return partial 537 * entries, even if there is room in the buffer. 538 */ 539 ent_per_req = param->nbytes_to_read / sizeof (logr_record_t); 540 if (ent_remain > ent_per_req) 541 ent_remain = ent_per_req; 542 543 if (ent_remain == 0) { 544 /* 545 * Send this error to Windows client so that it 546 * can figure out that there is no more record 547 * to read. 548 */ 549 param->buf = NDR_STRDUP(mxa, ""); 550 param->sent_size = 0; 551 param->status = NT_SC_ERROR(NT_STATUS_END_OF_FILE); 552 return (NDR_DRC_OK); 553 } 554 555 param->buf = NDR_MALLOC(mxa, param->nbytes_to_read); 556 buf = (BYTE *)param->buf; 557 558 for (ent_num = 0, ent_no = rdata->rd_last_sentrec; 559 ent_num < ent_remain; ent_num++, ent_no += dir) { 560 561 iter = ent_no & LOGR_NMSGMASK; 562 if (dir == LOGR_REW) 563 iter = (ent_no - 1) & LOGR_NMSGMASK; 564 565 le = logr_get_entry(rdata->rd_log, iter); 566 567 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 568 rec = (logr_record_t *)buf; 569 logr_set_logrecord(ctx->lc_source_name, le, ent_no, rec); 570 buf += sizeof (logr_record_t); 571 } 572 573 rdata->rd_last_sentrec = ent_no; 574 rdata->rd_first_read = 0; 575 576 param->sent_size = sizeof (logr_record_t) * ent_remain; 577 param->status = NT_STATUS_SUCCESS; 578 579 return (NDR_DRC_OK); 580 } 581