1 /* xstart.c --- Start libgsasl session.
2  * Copyright (C) 2002-2021 Simon Josefsson
3  *
4  * This file is part of GNU SASL Library.
5  *
6  * GNU SASL Library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * GNU SASL Library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License License along with GNU SASL Library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "internal.h"
24 
25 static Gsasl_mechanism *
find_mechanism(const char * mech,size_t n_mechs,Gsasl_mechanism * mechs)26 find_mechanism (const char *mech, size_t n_mechs, Gsasl_mechanism * mechs)
27 {
28   size_t i;
29 
30   if (mech == NULL)
31     return NULL;
32 
33   for (i = 0; i < n_mechs; i++)
34     if (strcmp (mech, mechs[i].name) == 0)
35       return &mechs[i];
36 
37   return NULL;
38 }
39 
40 static int
setup(Gsasl * ctx,const char * mech,Gsasl_session * sctx,size_t n_mechs,Gsasl_mechanism * mechs,int clientp)41 setup (Gsasl * ctx,
42        const char *mech,
43        Gsasl_session * sctx,
44        size_t n_mechs, Gsasl_mechanism * mechs, int clientp)
45 {
46   Gsasl_mechanism *mechptr = NULL;
47   int res;
48 
49   mechptr = find_mechanism (mech, n_mechs, mechs);
50   if (mechptr == NULL)
51     return GSASL_UNKNOWN_MECHANISM;
52 
53   sctx->ctx = ctx;
54   sctx->mech = mechptr;
55   sctx->clientp = clientp;
56 
57   if (clientp)
58     {
59       if (sctx->mech->client.start)
60 	res = sctx->mech->client.start (sctx, &sctx->mech_data);
61       else if (!sctx->mech->client.step)
62 	res = GSASL_NO_CLIENT_CODE;
63       else
64 	res = GSASL_OK;
65     }
66   else
67     {
68       if (sctx->mech->server.start)
69 	res = sctx->mech->server.start (sctx, &sctx->mech_data);
70       else if (!sctx->mech->server.step)
71 	res = GSASL_NO_SERVER_CODE;
72       else
73 	res = GSASL_OK;
74     }
75   if (res != GSASL_OK)
76     return res;
77 
78   return GSASL_OK;
79 }
80 
81 static int
start(Gsasl * ctx,const char * mech,Gsasl_session ** sctx,size_t n_mechs,Gsasl_mechanism * mechs,int clientp)82 start (Gsasl * ctx,
83        const char *mech,
84        Gsasl_session ** sctx,
85        size_t n_mechs, Gsasl_mechanism * mechs, int clientp)
86 {
87   Gsasl_session *out;
88   int res;
89 
90   out = calloc (1, sizeof (*out));
91   if (out == NULL)
92     return GSASL_MALLOC_ERROR;
93 
94   res = setup (ctx, mech, out, n_mechs, mechs, clientp);
95   if (res != GSASL_OK)
96     {
97       gsasl_finish (out);
98       return res;
99     }
100 
101   *sctx = out;
102 
103   return GSASL_OK;
104 }
105 
106 /**
107  * gsasl_client_start:
108  * @ctx: libgsasl handle.
109  * @mech: name of SASL mechanism.
110  * @sctx: pointer to client handle.
111  *
112  * This functions initiates a client SASL authentication.  This
113  * function must be called before any other gsasl_client_*() function
114  * is called.
115  *
116  * Return value: Returns %GSASL_OK if successful, or error code.
117  **/
118 int
gsasl_client_start(Gsasl * ctx,const char * mech,Gsasl_session ** sctx)119 gsasl_client_start (Gsasl * ctx, const char *mech, Gsasl_session ** sctx)
120 {
121   return start (ctx, mech, sctx, ctx->n_client_mechs, ctx->client_mechs, 1);
122 }
123 
124 /**
125  * gsasl_server_start:
126  * @ctx: libgsasl handle.
127  * @mech: name of SASL mechanism.
128  * @sctx: pointer to server handle.
129  *
130  * This functions initiates a server SASL authentication.  This
131  * function must be called before any other gsasl_server_*() function
132  * is called.
133  *
134  * Return value: Returns %GSASL_OK if successful, or error code.
135  **/
136 int
gsasl_server_start(Gsasl * ctx,const char * mech,Gsasl_session ** sctx)137 gsasl_server_start (Gsasl * ctx, const char *mech, Gsasl_session ** sctx)
138 {
139   return start (ctx, mech, sctx, ctx->n_server_mechs, ctx->server_mechs, 0);
140 }
141