"Fossies" - the Fresh Open Source Software Archive

Member "smbnetfs-0.6.3/src/auth.c" (2 Jan 2018, 9788 Bytes) of package /linux/misc/smbnetfs-0.6.3.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "auth.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.6.0_vs_0.6.1.

    1 #include "config.h"
    2 #include <pwd.h>
    3 #include <time.h>
    4 #include <stdlib.h>
    5 #include <string.h>
    6 #include <pthread.h>
    7 #include "list.h"
    8 #include "common.h"
    9 #include "auth-libsecret.h"
   10 #include "auth.h"
   11 
   12 struct authitem{
   13     char            *name;      // item name
   14     time_t          touch_time; // item touch time
   15     struct authinfo     *info;
   16     struct{
   17     int         child_cnt;  // number of subitem
   18     int         max_child_cnt;  // maximum number of subitem
   19     struct authitem     **childs;   // sorted list of subitems
   20     };
   21 };
   22 
   23 static char     auth_login[64]      = "guest";
   24 static char     *auth_fake_password = "********";
   25 static struct authinfo  authinfo_default    = {{NULL, NULL}, 1, "", auth_login, ""};
   26 static LIST     authinfo_list       = STATIC_LIST_INITIALIZER(authinfo_list);
   27 static struct authitem  authroot        = {NULL, (time_t) 0, NULL, {0, 0, NULL}};
   28 static pthread_mutex_t  m_auth          = PTHREAD_MUTEX_INITIALIZER;
   29 
   30 
   31 void auth_set_default_login_name(const char *name){
   32     strncpy(auth_login, name, sizeof(auth_login));
   33     auth_login[sizeof(auth_login) - 1] = '\0';
   34     DPRINTF(5, "login=%s\n", auth_login);
   35 }
   36 
   37 static struct authinfo * authinfo_create_new(
   38                 const char *domain,
   39                 const char *user,
   40                 const char *password){
   41 
   42     size_t      len;
   43     struct authinfo *info;
   44 
   45     len = sizeof(struct authinfo) +
   46         strlen(domain) + strlen(user) + strlen(password) + 3;
   47     if ((info = malloc(len)) == NULL) return NULL;
   48     memset(info, 0, len);
   49 
   50     info->domain   = (char *) (info + 1);
   51     info->user     = info->domain + strlen(domain) + 1;
   52     info->password = info->user + strlen(user) + 1;
   53 
   54     strcpy(info->domain,   domain);
   55     strcpy(info->user,     user);
   56     strcpy(info->password, password);
   57 
   58     return info;
   59 }
   60 
   61 static inline void authinfo_delete(struct authinfo *info){
   62     free(info);
   63 }
   64 
   65 static inline int authinfo_compare(struct authinfo *info,
   66                 const char *domain,
   67                 const char *user,
   68                 const char *password){
   69     return ((strcmp(info->domain,   domain)   == 0) &&
   70         (strcmp(info->user,     user)     == 0) &&
   71         (strcmp(info->password, password) == 0));
   72 }
   73 
   74 static struct authinfo * authinfo_find_in_list(
   75                 const char *domain,
   76                 const char *user,
   77                 const char *password){
   78 
   79     struct authinfo *info;
   80     LIST        *elem;
   81 
   82     elem = first_list_elem(&authinfo_list);
   83     while(is_valid_list_elem(&authinfo_list, elem)){
   84     info = list_entry(elem, struct authinfo, entries);
   85     if (authinfo_compare(info, domain, user, password)) return info;
   86     elem = elem->next;
   87     }
   88     return NULL;
   89 }
   90 
   91 static struct authinfo * authinfo_store_list(
   92                 const char *domain,
   93                 const char *user,
   94                 const char *password){
   95 
   96     struct authinfo *info;
   97 
   98     DPRINTF(10, "domain=%s, user=%s, password=%s\n",
   99             domain, user, auth_fake_password);
  100 
  101     info = authinfo_find_in_list(domain, user, password);
  102     if (info != NULL){
  103     remove_from_list(&authinfo_list, &info->entries);
  104     }else{
  105     info = authinfo_create_new(domain, user, password);
  106     if (info == NULL) return NULL;
  107     }
  108 
  109     info->ref_count++;
  110     add_to_list_back(&authinfo_list, &info->entries);
  111     return info;
  112 }
  113 
  114 static void authinfo_release(struct authinfo *info){
  115     info->ref_count--;
  116     if (info->ref_count == 0){
  117     remove_from_list(&authinfo_list, &info->entries);
  118     authinfo_delete(info);
  119     }
  120 }
  121 
  122 static struct authitem* authitem_create_item(const char *name){
  123     struct authitem *item;
  124 
  125     item = malloc(sizeof(struct authitem) + strlen(name) + 1);
  126     if (item == NULL) return NULL;
  127 
  128     memset(item, 0 , sizeof(struct authitem));
  129     item->name = (char *) (item + 1);
  130     strcpy(item->name, name);
  131     item->touch_time = time(NULL);
  132     return item;
  133 }
  134 
  135 static inline void authitem_delete_item(struct authitem *item){
  136     if (item->info != NULL) authinfo_release(item->info);
  137     if (item->childs != NULL) free(item->childs);
  138     free(item);
  139 }
  140 
  141 static void authitem_delete_obsolete_items(struct authitem *item, time_t threshold){
  142     int     i;
  143 
  144     for(i = item->child_cnt - 1; i >= 0; i--){
  145     authitem_delete_obsolete_items(item->childs[i], threshold);
  146     if ((item->childs[i]->info == NULL) && 
  147         (item->childs[i]->childs == NULL)){
  148 
  149         authitem_delete_item(item->childs[i]);
  150         if (i != item->child_cnt - 1){
  151         memmove(&item->childs[i],
  152             &item->childs[i + 1],
  153             (item->child_cnt - i - 1) * sizeof(struct authitem *));
  154         }
  155         item->child_cnt--;
  156     }
  157     }
  158     if ((item->touch_time < threshold) && (item->info != NULL)){
  159     authinfo_release(item->info);
  160     item->info = NULL;
  161     }
  162     if ((item->child_cnt == 0) && (item->childs != NULL)){
  163     free(item->childs);
  164     item->childs = NULL;
  165     item->max_child_cnt = 0;
  166     }
  167 }
  168 
  169 /*
  170  * This function search for an item in specified authitem subitems,
  171  * subitems MUST be sorted alphabetically, so we can bisect.
  172  *
  173  * return:
  174  *   a) item position, if item with specified name was found
  175  *   b) negative value -(pos+1), if item was not found,
  176  *      where 'pos' is the position to insert the new element
  177  */
  178 static int authitem_find_subitem(struct authitem *item, const char *name){
  179     int     first = 0, last = item->child_cnt - 1;
  180 
  181     while(first <= last){
  182     int i       = (first + last) >> 1;
  183     int result  = strcasecmp(item->childs[i]->name, name);
  184 
  185     if (result == 0) return i;
  186     if (result < 0) first = i + 1;
  187     else last = i - 1;
  188     }
  189     return -(first + 1);
  190 }
  191 
  192 /*
  193  * This function insert an element to specified authitem,
  194  * insert position MUST be obtained with authitem_find_subitem().
  195  *
  196  * return:
  197  *   a) zero, if no errors
  198  *   b) (-1), if insertion failed
  199  */
  200 static int authitem_insert_subitem(struct authitem *item,
  201                 struct authitem *subitem, int pos){
  202     if ((pos > item->child_cnt) || (pos < 0)) return -1;
  203 
  204     if (item->max_child_cnt == item->child_cnt){
  205     struct authitem **new_childs;
  206     int     new_max_cnt;
  207 
  208     new_max_cnt = (item->max_child_cnt == 0) ?
  209             64 : 2 * item->max_child_cnt;
  210     new_childs = realloc(item->childs,
  211             new_max_cnt * sizeof(struct authitem *));
  212     if (new_childs == NULL) return -1;
  213 
  214     item->max_child_cnt = new_max_cnt;
  215     item->childs = new_childs;
  216     }
  217 
  218     if (pos < item->child_cnt){
  219     memmove(&item->childs[pos + 1],
  220         &item->childs[pos],
  221         (item->child_cnt - pos) * sizeof(struct authitem *));
  222     }
  223     item->childs[pos] = subitem;
  224     item->child_cnt++;
  225     return 0;
  226 }
  227 
  228 static struct authitem * authitem_get_subitem(
  229                 struct authitem *item,
  230                 const char *name){
  231     int         pos;
  232     struct authitem *subitem;
  233 
  234     pos = authitem_find_subitem(item, name);
  235     if (pos < 0){
  236     /* create new subitem and add it to item */
  237     subitem = authitem_create_item(name);
  238     if (subitem == NULL) return NULL;
  239     pos = -(pos + 1);
  240     if (authitem_insert_subitem(item, subitem, pos) != 0){
  241         authitem_delete_item(subitem);
  242         return NULL;
  243     }
  244     }
  245     return item->childs[pos];
  246 }
  247 
  248 struct authinfo * auth_get_authinfo(
  249                 const char *domain,
  250                 const char *server,
  251                 const char *share,
  252                 int *suitability){
  253 
  254     int         pos;
  255     struct authitem *item;
  256     struct authinfo *info;
  257 
  258     DPRINTF(10, "domain=%s, server=%s, share=%s\n", domain, server, share);
  259 
  260     if ((server == NULL) || (*server == '\0')) return NULL;
  261     if (domain == NULL) domain = "";
  262     if (share  == NULL) share  = "";
  263 
  264     item = &authroot;
  265     info = &authinfo_default;
  266     *suitability = AUTH_FALLBACK;
  267     pthread_mutex_lock(&m_auth);
  268     if (item->info != NULL){
  269         info = item->info;
  270         *suitability = AUTH_MATCH_DEFAULT;
  271     }
  272     if (*domain != '\0'){
  273         pos = authitem_find_subitem(item, domain);
  274         if ((pos >= 0) && (item->childs[pos]->info != NULL)){
  275         info = item->childs[pos]->info;
  276         *suitability = AUTH_MATCH_DOMAIN_COMPAT;
  277         }
  278     }
  279 
  280     if ((pos = authitem_find_subitem(item, server)) < 0) goto end;
  281     item = item->childs[pos];
  282     if (item->info != NULL){
  283         info = item->info;
  284         *suitability = AUTH_MATCH_SERVER;
  285     }
  286 
  287     if (*share == '\0') goto end;
  288     if ((pos = authitem_find_subitem(item, share)) < 0) goto end;
  289     item = item->childs[pos];
  290     if (item->info != NULL){
  291         info = item->info;
  292         *suitability = AUTH_MATCH_RESOURCE;
  293     }
  294 
  295       end:
  296         info->ref_count++;
  297     pthread_mutex_unlock(&m_auth);
  298     DPRINTF(10, "domain=%s, user=%s, password=%s, suitability=%d\n",
  299         info->domain, info->user, auth_fake_password, *suitability);
  300     return info;
  301 }
  302 
  303 void auth_release_authinfo(struct authinfo *info){
  304     pthread_mutex_lock(&m_auth);
  305     authinfo_release(info);
  306     pthread_mutex_unlock(&m_auth);
  307 }
  308 
  309 int auth_store_auth_data(const char *server,
  310                 const char *share,
  311                 const char *domain,
  312                 const char *user,
  313                 const char *password){
  314 
  315     int         result;
  316     struct authinfo *info;
  317     struct authitem *item;
  318 
  319     DPRINTF(10, "smb://%s/%s, domain=%s, user=%s, password=%s\n",
  320             server, share, domain, user, auth_fake_password);
  321 
  322     if ((user == NULL) || (*user == '\0')) return -1;
  323     if (server   == NULL) server   = "";
  324     if (share    == NULL) share    = "";
  325     if (domain   == NULL) domain   = "";
  326     if (password == NULL) password = "";
  327     if ((*server == '\0') && (*share != '\0')) return -1;
  328 
  329     result = -1;
  330     item = &authroot;
  331     pthread_mutex_lock(&m_auth);
  332     if (*server == '\0') goto update_info;
  333     if ((item = authitem_get_subitem(item, server)) == NULL) goto error;
  334 
  335     if (*share == '\0') goto update_info;
  336     if ((item = authitem_get_subitem(item, share)) == NULL) goto error;
  337 
  338       update_info:
  339     if ((item->info == NULL) ||
  340         ! authinfo_compare(item->info, domain, user, password)){
  341 
  342         info = authinfo_store_list(domain, user, password);
  343         if (info == NULL) goto error;
  344         if (item->info != NULL) authinfo_release(item->info);
  345         item->info = info;
  346     }
  347     item->touch_time = time(NULL);
  348     result = 0;
  349 
  350       error:
  351     pthread_mutex_unlock(&m_auth);
  352     return result;
  353 }
  354 
  355 void auth_delete_obsolete(time_t threshold){
  356     pthread_mutex_lock(&m_auth);
  357     authitem_delete_obsolete_items(&authroot, threshold);
  358     pthread_mutex_unlock(&m_auth);
  359 }