2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) Rafal Szczesniak 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "libsmb/samlogon_cache.h"
23 #include "../librpc/gen_ndr/netlogon.h"
24 #include "../librpc/gen_ndr/ndr_netlogon.h"
25 #include "libcli/security/dom_sid.h"
26 #include "lib/util/strv.h"
27 #include "lib/gencache.h"
31 * @brief This is part of the net tool which is basically command
32 * line wrapper for gencache.c functions (mainly for testing)
38 * These routines are used via gencache_iterate() to display the cache's contents
39 * (print_cache_entry) and to flush it (delete_cache_entry).
40 * Both of them are defined by first arg of gencache_iterate() routine.
42 static void print_cache_entry(const char* keystr
, DATA_BLOB value
,
43 const time_t timeout
, void* dptr
)
46 char *alloc_str
= NULL
;
48 char *datastr_free
= NULL
;
49 time_t now_t
= time(NULL
);
50 struct tm timeout_tm
, now_tm
;
51 struct tm
*ptimeout_tm
, *pnow_tm
;
53 ptimeout_tm
= localtime_r(&timeout
, &timeout_tm
);
54 if (ptimeout_tm
== NULL
) {
57 pnow_tm
= localtime_r(&now_t
, &now_tm
);
58 if (pnow_tm
== NULL
) {
62 /* form up timeout string depending whether it's today's date or not */
63 if (timeout_tm
.tm_year
!= now_tm
.tm_year
||
64 timeout_tm
.tm_mon
!= now_tm
.tm_mon
||
65 timeout_tm
.tm_mday
!= now_tm
.tm_mday
) {
67 timeout_str
= asctime(&timeout_tm
);
71 timeout_str
[strlen(timeout_str
) - 1] = '\0'; /* remove tailing CR */
73 if (asprintf(&alloc_str
, "%.2d:%.2d:%.2d", timeout_tm
.tm_hour
,
74 timeout_tm
.tm_min
, timeout_tm
.tm_sec
) == -1) {
77 timeout_str
= alloc_str
;
80 datastr
= (char *)value
.data
;
82 if (strnequal(keystr
, "NAME2SID/", strlen("NAME2SID/"))) {
83 const char *strv
= (char *)value
.data
;
84 size_t strv_len
= value
.length
;
85 const char *sid
= strv_len_next(strv
, strv_len
, NULL
);
86 const char *type
= strv_len_next(strv
, strv_len
, sid
);
87 datastr
= talloc_asprintf(talloc_tos(), "%s (%s)", sid
, type
);
90 if (strnequal(keystr
, "SID2NAME/", strlen("SID2NAME/"))) {
91 const char *strv
= (char *)value
.data
;
92 size_t strv_len
= value
.length
;
93 const char *domain
= strv_len_next(strv
, strv_len
, NULL
);
94 const char *name
= strv_len_next(strv
, strv_len
, domain
);
95 const char *type
= strv_len_next(strv
, strv_len
, name
);
96 datastr
= talloc_asprintf(talloc_tos(), "%s\\%s (%s)",
100 if ((value
.length
> 0) && (value
.data
[value
.length
-1] != '\0')) {
101 datastr_free
= talloc_asprintf(
102 talloc_tos(), "<binary length %d>",
104 datastr
= datastr_free
;
105 if (datastr
== NULL
) {
106 datastr
= "<binary>";
110 d_printf(_("Key: %s\t Timeout: %s\t Value: %s %s\n"), keystr
,
111 timeout_str
, datastr
, timeout
> now_t
? "": _("(expired)"));
113 SAFE_FREE(alloc_str
);
116 static void delete_cache_entry(const char* keystr
, const char* datastr
,
117 const time_t timeout
, void* dptr
)
119 if (!gencache_del(keystr
))
120 d_fprintf(stderr
, _("Couldn't delete entry! key = %s\n"),
126 * Parse text representation of timeout value
128 * @param timeout_str string containing text representation of the timeout
129 * @return numeric timeout of time_t type
131 static time_t parse_timeout(const char* timeout_str
)
133 char sign
= '\0', *number
= NULL
, unit
= '\0';
134 int len
, number_begin
, number_end
;
138 if (timeout_str
[0] == '!' || timeout_str
[0] == '+') {
139 sign
= timeout_str
[0];
146 len
= strlen(timeout_str
);
147 switch (timeout_str
[len
- 1]) {
152 case 'w': unit
= timeout_str
[len
- 1];
155 /* number detection */
156 len
= (sign
) ? strlen(&timeout_str
[number_begin
]) : len
;
157 number_end
= (unit
) ? len
- 1 : len
;
158 number
= SMB_STRNDUP(&timeout_str
[number_begin
], number_end
);
160 /* calculate actual timeout value */
161 timeout
= (time_t)atoi(number
);
164 case 'm': timeout
*= 60; break;
165 case 'h': timeout
*= 60*60; break;
166 case 'd': timeout
*= 60*60*24; break;
167 case 'w': timeout
*= 60*60*24*7; break; /* that's fair enough, I think :) */
171 case '!': timeout
= time(NULL
) - timeout
; break;
173 default: timeout
+= time(NULL
); break;
176 if (number
) SAFE_FREE(number
);
182 * Add an entry to the cache. If it does exist, then set it.
184 * @param c A net_context structure
185 * @param argv key, value and timeout are passed in command line
186 * @return 0 on success, otherwise failure
188 static int net_cache_add(struct net_context
*c
, int argc
, const char **argv
)
190 const char *keystr
, *datastr
, *timeout_str
;
193 if (argc
< 3 || c
->display_usage
) {
196 _("net cache add <key string> <data string> "
203 timeout_str
= argv
[2];
205 /* parse timeout given in command line */
206 timeout
= parse_timeout(timeout_str
);
208 d_fprintf(stderr
, _("Invalid timeout argument.\n"));
212 if (gencache_set(keystr
, datastr
, timeout
)) {
213 d_printf(_("New cache entry stored successfully.\n"));
217 d_fprintf(stderr
, _("Entry couldn't be added. Perhaps there's already such a key.\n"));
222 * Delete an entry in the cache
224 * @param c A net_context structure
225 * @param argv key to delete an entry of
226 * @return 0 on success, otherwise failure
228 static int net_cache_del(struct net_context
*c
, int argc
, const char **argv
)
230 const char *keystr
= argv
[0];
232 if (argc
< 1 || c
->display_usage
) {
235 _(" net cache del <key string>\n"));
239 if(gencache_del(keystr
)) {
240 d_printf(_("Entry deleted.\n"));
244 d_fprintf(stderr
, _("Couldn't delete specified entry\n"));
250 * Get and display an entry from the cache
252 * @param c A net_context structure
253 * @param argv key to search an entry of
254 * @return 0 on success, otherwise failure
256 static int net_cache_get(struct net_context
*c
, int argc
, const char **argv
)
258 const char* keystr
= argv
[0];
262 if (argc
< 1 || c
->display_usage
) {
265 _(" net cache get <key>\n"));
269 if (gencache_get_data_blob(keystr
, NULL
, &value
, &timeout
, NULL
)) {
270 print_cache_entry(keystr
, value
, timeout
, NULL
);
271 data_blob_free(&value
);
275 d_fprintf(stderr
, _("Failed to find entry\n"));
281 * Search an entry/entries in the cache
283 * @param c A net_context structure
284 * @param argv key pattern to match the entries to
285 * @return 0 on success, otherwise failure
287 static int net_cache_search(struct net_context
*c
, int argc
, const char **argv
)
291 if (argc
< 1 || c
->display_usage
) {
294 _(" net cache search <pattern>\n"));
299 gencache_iterate_blobs(print_cache_entry
, NULL
, pattern
);
305 * List the contents of the cache
307 * @param c A net_context structure
308 * @param argv ignored in this functionailty
309 * @return always returns 0
311 static int net_cache_list(struct net_context
*c
, int argc
, const char **argv
)
313 const char* pattern
= "*";
315 if (c
->display_usage
) {
320 _("List all cache entries."));
323 gencache_iterate_blobs(print_cache_entry
, NULL
, pattern
);
329 * Flush the whole cache
331 * @param c A net_context structure
332 * @param argv ignored in this functionality
333 * @return always returns 0
335 static int net_cache_flush(struct net_context
*c
, int argc
, const char **argv
)
337 const char* pattern
= "*";
338 if (c
->display_usage
) {
343 _("Delete all cache entries."));
346 gencache_iterate(delete_cache_entry
, NULL
, pattern
);
350 static int netsamlog_cache_for_all_cb(const char *sid_str
,
352 struct netr_SamInfo3
*info3
,
355 struct net_context
*c
= (struct net_context
*)private_data
;
358 name
= talloc_asprintf(c
, "%s\\%s",
359 info3
->base
.logon_domain
.string
,
360 info3
->base
.account_name
.string
);
365 d_printf("%-50s %-40s %s\n",
368 timestring(c
, when_cached
));
373 static int net_cache_samlogon_list(struct net_context
*c
,
379 d_printf("%-50s %-40s When cached\n", "SID", "Name");
380 d_printf("------------------------------------------------------------"
381 "------------------------------------------------------------"
384 ret
= netsamlog_cache_for_all(netsamlog_cache_for_all_cb
, c
);
392 static int net_cache_samlogon_show(struct net_context
*c
,
396 const char *sid_str
= argv
[0];
398 struct dom_sid
*user_sids
= NULL
;
399 uint32_t num_user_sids
;
400 struct netr_SamInfo3
*info3
= NULL
;
406 if (argc
!= 1 || c
->display_usage
) {
408 "net cache samlogon show SID\n"
411 _("Show samlogon cache entry for SID."));
415 ok
= string_to_sid(&sid
, sid_str
);
417 d_printf("String to SID failed for %s\n", sid_str
);
421 info3
= netsamlogon_cache_get(c
, &sid
);
423 d_printf("SID %s not found in samlogon cache\n", sid_str
);
427 name
= talloc_asprintf(c
, "%s\\%s",
428 info3
->base
.logon_domain
.string
,
429 info3
->base
.account_name
.string
);
434 d_printf("Name: %s\n", name
);
436 status
= sid_array_from_info3(c
,
441 if (!NT_STATUS_IS_OK(status
)) {
442 TALLOC_FREE(user_sids
);
443 d_printf("sid_array_from_info3 failed for %s\n", sid_str
);
447 for (i
= 0; i
< num_user_sids
; i
++) {
448 struct dom_sid_buf buf
;
449 d_printf("SID %2" PRIu32
": %s\n",
451 dom_sid_str_buf(&user_sids
[i
], &buf
));
454 TALLOC_FREE(user_sids
);
459 static int net_cache_samlogon_ndrdump(struct net_context
*c
,
463 const char *sid_str
= NULL
;
465 struct netr_SamInfo3
*info3
= NULL
;
466 struct ndr_print
*ndr_print
= NULL
;
469 if (argc
!= 1 || c
->display_usage
) {
471 "net cache samlogon ndrdump SID\n"
474 _("Show samlogon cache entry for SID."));
480 ok
= string_to_sid(&sid
, sid_str
);
482 d_printf("String to SID failed for %s\n", sid_str
);
486 info3
= netsamlogon_cache_get(c
, &sid
);
488 d_printf("SID %s not found in samlogon cache\n", sid_str
);
492 ndr_print
= talloc_zero(c
, struct ndr_print
);
493 if (ndr_print
== NULL
) {
494 d_printf("Could not allocate memory.\n");
498 ndr_print
->print
= ndr_print_printf_helper
;
499 ndr_print
->depth
= 1;
500 ndr_print_netr_SamInfo3(ndr_print
, "netr_SamInfo3", info3
);
501 TALLOC_FREE(ndr_print
);
506 static int net_cache_samlogon_delete(struct net_context
*c
,
510 const char *sid_str
= argv
[0];
514 if (argc
!= 1 || c
->display_usage
) {
516 "net cache samlogon delete SID\n"
519 _("Delete samlogon cache entry for SID."));
523 ok
= string_to_sid(&sid
, sid_str
);
525 d_printf("String to SID failed for %s\n", sid_str
);
529 netsamlogon_clear_cached_user(&sid
);
534 static int net_cache_samlogon(struct net_context
*c
, int argc
, const char **argv
)
536 struct functable func
[] = {
539 net_cache_samlogon_list
,
541 N_("List samlogon cache"),
542 N_("net cache samlogon list\n"
543 " List samlogon cachen\n")
547 net_cache_samlogon_show
,
549 N_("Show samlogon cache entry"),
550 N_("net cache samlogon show SID\n"
551 " Show samlogon cache entry\n")
555 net_cache_samlogon_ndrdump
,
557 N_("Dump the samlogon cache entry NDR blob"),
558 N_("net cache samlogon ndrdump SID\n"
559 " Dump the samlogon cache entry NDR blob\n")
563 net_cache_samlogon_delete
,
565 N_("Delete samlogon cache entry"),
566 N_("net cache samlogon delete SID\n"
567 " Delete samlogon cache entry\n")
569 {NULL
, NULL
, 0, NULL
, NULL
}
572 return net_run_function(c
, argc
, argv
, "net cache samlogon", func
);
576 * Entry point to 'net cache' subfunctionality
578 * @param c A net_context structure
579 * @param argv arguments passed to further called functions
580 * @return whatever further functions return
582 int net_cache(struct net_context
*c
, int argc
, const char **argv
)
584 struct functable func
[] = {
589 N_("Add new cache entry"),
590 N_("net cache add <key string> <data string> <timeout>\n"
591 " Add new cache entry.\n"
592 " key string\tKey string to add cache data under.\n"
593 " data string\tData to store under given key.\n"
594 " timeout\tTimeout for cache data.")
600 N_("Delete existing cache entry by key"),
601 N_("net cache del <key string>\n"
602 " Delete existing cache entry by key.\n"
603 " key string\tKey string to delete.")
609 N_("Get cache entry by key"),
610 N_("net cache get <key string>\n"
611 " Get cache entry by key.\n"
612 " key string\tKey string to look up cache entry for.")
619 N_("Search entry by pattern"),
620 N_("net cache search <pattern>\n"
621 " Search entry by pattern.\n"
622 " pattern\tPattern to search for in cache.")
628 N_("List all cache entries"),
629 N_("net cache list\n"
630 " List all cache entries")
636 N_("Delete all cache entries"),
637 N_("net cache flush\n"
638 " Delete all cache entries")
644 N_("List contents of the samlogon cache"),
645 N_("net cache samlogon\n"
646 " List contents of the samlogon cache")
648 {NULL
, NULL
, 0, NULL
, NULL
}
651 return net_run_function(c
, argc
, argv
, "net cache", func
);