afpfs-ng-mac/lib/proto_session.c

152 lines
3.3 KiB
C

/*
* sesssion.c
*
* Copyright (C) 2007 Alex deVries
*
*/
#include <stdlib.h>
#include <string.h>
#include "afpfs-ng/dsi.h"
#include "dsi_protocol.h"
#include "afpfs-ng/afp.h"
#include "afpfs-ng/utils.h"
int afp_getsessiontoken(struct afp_server * server, int type,
unsigned int timestamp, struct afp_token *outgoing_token,
struct afp_token * incoming_token)
{
struct {
struct dsi_header header __attribute__((__packed__));
uint8_t command;
uint8_t pad;
uint16_t type;
uint32_t idlength;
} __attribute__((__packed__)) * request;
int ret=0;
int offset=0;
int datalen=0;
char * data;
int timelen=0;
datalen=outgoing_token->length;
request=malloc(sizeof(*request) +AFP_TOKEN_MAX_LEN +sizeof(timestamp));
switch (type) {
case kLoginWithTimeAndID:
case kReconnWithTimeAndID: {
uint32_t *p = (void *) (((unsigned long) request)+
sizeof(*request));
offset=sizeof(timestamp);
*p = timestamp;
timelen=sizeof(timestamp);
}
break;
case kRecon1Login:
break;
case kLoginWithoutID:
case kRecon1Refresh:
case kRecon1ReconnectLogin:
datalen=0;
break;
case kGetKerberosSessionKey: /* We don't support it */
case kReconnWithID:/* Deprecated. */
case kLoginWithID: /* Deprecated. */
default:
ret=-1;
free(request);
goto error;
}
data=(void *) (((unsigned long) request)+sizeof(*request)+offset);
request->idlength=htonl(datalen);
request->pad=0;
request->type=htons(type);
dsi_setup_header(server, &request->header, DSI_DSICommand);
request->command = afpGetSessionToken;
memcpy(data,outgoing_token->data,datalen);
ret = dsi_send(server, (char *)request,
sizeof(*request) + datalen + timelen,
DSI_DEFAULT_TIMEOUT, afpGetSessionToken,
(void *) incoming_token);
free(request);
return 0;
error:
return ret;
}
int afp_getsessiontoken_reply(struct afp_server *server, char *buf,
unsigned int size, void * other) {
struct afp_token * token = other;
struct {
struct dsi_header header __attribute__((__packed__));
uint32_t token_len;
} * reply = (void *)buf;
char * token_data = buf + sizeof(*reply);
unsigned int token_len;
if (ntohl(reply->header.length)<=sizeof(struct dsi_header)) {
if (token) token->length=0;
return 0;
}
token_len=ntohl(reply->token_len);
if ((token_len>AFP_TOKEN_MAX_LEN) ||
(ntohl(reply->header.length)-sizeof(struct dsi_header) < token_len))
return -1;
if (token) {
memcpy(token->data,token_data,token_len);
token->length=token_len;
}
return 0;
}
int afp_disconnectoldsession(struct afp_server * server, int type,
struct afp_token * token)
{
struct {
struct dsi_header header __attribute__((__packed__));
uint8_t command;
uint8_t pad;
uint16_t type;
uint32_t idlength;
} __attribute__((__packed__)) * request;
char * token_data;
int ret;
if ((request=malloc(sizeof(*request) + AFP_TOKEN_MAX_LEN))==NULL)
return -1;
token_data = (char *)request + sizeof(*request);
request->type=htons(type);
if (token->length>AFP_TOKEN_MAX_LEN) return -1;
dsi_setup_header(server, &request->header, DSI_DSICommand);
request->command = afpDisconnectOldSession;
request->idlength=htonl(token->length);
memcpy(token_data,token->data,token->length);
ret = dsi_send(server, (char *)request,
sizeof(*request) + token->length,
DSI_DEFAULT_TIMEOUT, afpDisconnectOldSession, NULL);
free(request);
return ret;
}